Supponiamo che io ho una classe dipendente che sembra qualcosa di simile:Angular2: come trasformare il mio modello ad albero per adattarlo ad un'interfaccia diversa?
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;
}
}
Supponiamo di avere iniziali Employee
s che sembrano qualcosa di simile:
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;
}
Possiamo anche assumere che a volte i dipendenti saranno essere assunto o licenziato. Qualcosa sulla falsariga di questo:
window.setTimeout(()=>{
let someEmployee: Employee = /* Some existing employee */
someEmployee.addWorker("someTitle", "someName", "someLastName");
}, someAmountOfTime);
Voglio visualizzare i dipendenti in un PrimeNg tree.
L'albero widget di richiede che i dati da visualizzare conforme all'interfaccia TreeNode, che assomiglia a questo:
export interface TreeNode {
label?: string;
data?: any;
icon?: any;
expandedIcon?: any;
collapsedIcon?: any;
children?: TreeNode[];
leaf?: boolean;
}
Domanda principale: Senza cambiare la mia classe Employee, qual è il modo migliore per trasformare i dati in TreeNodes?
Cose che io sto pensando:
- Quando aggiungo un nuovo dipendente, voglio mantenere il mio stato albero (ciò che è aperto, ciò che è stato selezionato, ecc)
- ho bisogno essere in grado di recuperare facilmente il dipendente che è attualmente selezionato.
- Sto cercando di evitare di mantenere due modelli duplicati.
- voglio approfittare di rilevamento delle modifiche di Angular2 in un ragionevole, ma il modo scalabile
Questo è ciò che il mio EmployeeTree componente assomigliare al momento:
@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;
}
Opzione 1 - Creare una pipe che trasformerà un dipendente in TreeNode
Credo che sarebbe lasciare il mio modello simile a questo:
<p-tree [value]="owner | convertToTreeNode"></p-tree>
e vorrei creare un tubo che ha fatto qualcosa di simile:
@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;
}
}
Pro/Contro:
- Questo sfrutta il rilevamento del cambio angolare
- Se si tratta di un tubo puro, potrebbero perdere le modifiche
- Se si tratta di un tubo impura, può essere troppo pesante
- Lascia la componente molto pulito e delega la responsabilità al tubo
- Non sono sicuro se questo sarà preservare il mio stato gui (quello che viene selezionato e ciò che è aperto/chiuso) quando un nuovo articolo si aggiunge
Opzione 2 - All'interno della componente di mantenere una struttura separata per l'albero
@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
}
Penso che potrei far sì che il Dipendente emetta un evento che gocciola quando cambia. Questo potrebbe darmi qualcosa a cui aggrapparmi.
In generale, qual è il modo migliore di utilizzare Angular2 per fare qualcosa di simile.
In sintesi, voglio usare un widget che si aspetta i dati in un formato leggermente più diverso rispetto a quello che sto riporlo in. Qual è il modo angular2 standard per massaggiare i miei dati nel widget di? C'è una speciale salsa angular2 che mi aiuterà qui? Devo mantenere due modelli separati? Potenzialmente il mio albero potrebbe contenere 100 o forse 1000 di elementi, quindi sono piuttosto interessato alle prestazioni.