假设我的员工类看起来像这样:
export class Employee {
jobTitle: string;
firstName: string;
lastName: string;
boss: Employee;
workers: Employee[];
constructor(jobTitle: string, firstName: string, lastName: string){
this.jobTitle = jobTitle;
this.firstName = firstName;
this.lastName = lastName;
}
public addWorker(worker: Employee){
this.wokers.push(worker);
worker.boss = this;
}
}
假设我们的初始Employee
看起来像这样:
function getInitialStaff(): Employee {
let headWaiter: Employee = new Employee( "Head Waiter", "Sarah", "Hilton" );
headWaiter.addWorker(new Employee("Bus Boy", "Joe", "BeefEater"));
headWaiter.addWorker(new Employee("Waiter", "Randy", "Rainman"));
let headCheif: Employee = new Employee( "Head Cheif", "Phil", "Yorstomux" );
headWaiter.addWorker(new Employee("Dishwasher", "Andy", "Shark"));
let owner: Employee = new Employee( "Owner", "Boris", "Laughington" );
owner.addWorker(headWaiter);
owner.addWorker(headCheif);
return owner;
}
我们还可以假设有时员工会被雇用或解雇。有点像这样:
window.setTimeout(()=>{
let someEmployee: Employee = /* Some existing employee */
someEmployee.addWorker("someTitle", "someName", "someLastName");
}, someAmountOfTime);
我希望以PrimeNg tree显示员工。
树窗口小部件要求显示的数据符合treeNode接口,如下所示:
export interface TreeNode {
label?: string;
data?: any;
icon?: any;
expandedIcon?: any;
collapsedIcon?: any;
children?: TreeNode[];
leaf?: boolean;
}
主要问题:如果不更改我的Employee类,将数据转换为TreeNodes的最佳方法是什么?
我正在考虑的事情:
这就是我的EmployeeTree组件目前的样子:
@Component({
selector: 'employee-tree',
template: `
<div>
<p-tree>
/* Open Question, I need to transform owner and then tie the resulting TreeNode to the tree */
</p-tree>
</div>
`
directives: [ Tree ]
})
export class EmployeeTree {
@Input()
private owner: Employee;
}
选项1 - 创建一个将Employee转换为TreeNode的管道
我想这会让我的模板看起来像这样:
<p-tree [value]="owner | convertToTreeNode"></p-tree>
我会创建一个像这样的管道:
@Pipe({name: 'convertToTreeNode'})
export class ToTreeNode implements PipeTransform {
transform(employee: Employee): TreeNode {
let treeNode: TreeNode = {
label: employee.firstName + " " + employee.lastName,
data: employee,
children: []
};
employee.workers.forEach(worker => {
treeNode.children.push(this.transform(worker));
})
return treeNode;
}
}
优点/缺点:
选项2 - 组件内部为树
维护一个单独的结构@Component({
selector: 'employee-tree',
template: `
<div>
<p-tree [data]="employeeTree">
</p-tree>
</div>
`
directives: [ Tree ]
})
export class EmployeeTree {
@Input()
private owner: Employee;
private employeeTree: TreeNode;
// TODO - Somehow watch the owner for changes (how?) and then repopulate the employeeTree
}
我认为我可以让Employee发出一个在它发生变化时涓涓细流的事件。这可以给我一些东西。
一般来说,使用Angular2做这样的事情的最佳方法是什么。
总而言之,我想使用一个小部件,它希望数据采用与我存储的略微不同格式的格式。将数据按入窗口小部件的标准angular2方法是什么?是否有特殊的角度酱可以帮助我?我应该保留两个单独的型号吗?我的树可能有100个或者可能有1000个物品,所以我有点担心性能。
答案 0 :(得分:0)
我会使用Lodash map。这是他们的罐头示例:
import * as _ from 'lodash';
var users = [
{ 'user': 'barney' },
{ 'user': 'fred' }
];
// The `_.property` iteratee shorthand.
_.map(users, 'user');
// => ['barney', 'fred']
这是我对此的歪曲:
let emplData = [
{ "jobTitle": "Paperboy",
"firstName": "Fred",
"lastName": "Bloggs"
},
{ "jobTitle": "Tea boy",
"firstName": "Charlie",
"lastName": "Creamslice"
}
]
let resEl = document.getElementById("result");
resEl.innerText =JSON.stringify(emplData.map(buildEmployeeNamesOnlyAndAddSeqNo));
function buildEmployeeNamesOnlyAndAddSeqNo({firstName,lastName},index) {
return {seqNo:index, firstName, lastName}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.16.2/lodash.js"></script>
<div id="result">
</div>
答案 1 :(得分:0)
您可以拥有Employee的子类,它符合TreeNode
然后在你的组件中
@Component({
selector: 'employee-tree',
template: `
<div>
<p-tree [data]="employeeNode.label">
</p-tree>
</div>
`
directives: [ Tree ]
})
export class EmployeeNode extends Employee implements TreeNode {
// -- No need for this anymore -- @Input() private owner: EmployeeNode;
@Input() private jobTitleInput: String;
@Input() private firstNameInput: String;
@Input() private lastNameInput: String;
constructor(){
super(jobTitleInput, firstNameInput, lastNameInput);
// Populate TreeNode here for example label from TreeNode
this.label = `${firstName} ${lastName}`;
}
//private employeeTree: TreeNode; -- No need for TreeNode object any more as EmployeeNode contains both TreeNode and Employee
// TODO - Somehow watch the owner for changes (how?) and then repopulate the employeeTree : Just add a setter for each property
of Employee that you want to also affect TreeNode field and inside that setter update in your EmployeeNode class the field of TreeNode Interface like 'this.label = 'updated value'
}