2016-04-09 26 views
6

Sto imparando Angular 2, cercando di costruire una vista ad albero espandibile da un'API di terze parti (potenzialmente molto grande). L'API ha una struttura sottostante simili:Miglior approccio per creare dinamicamente una vista ad albero ricorsiva dall'API dei dati

- Home (id: 1053) 
- - Rugby League (id: 1054) 
- - - Super League (id: 1103) 
- - - - Castleford Tigers (id: 1111) 
- - - - Catalans Dragons (id: 1110) 
- - - - Huddersfield Giants (id: 1116) 
- - - - Hull FC (id: 1108) 
- - - Championship (id: 1104) 
- - - - Batley Bulldogs (id: 1120) 
- - - - Bradford Bulls (id: 1118) 
- - - - Dewsbury Rams (id: 1124) 
- - - - Featherstone Rovers (id: 1121) 
- - Football (id: 1056) 
- - - Premier League (id: 1057) 
- - - - AFC Bournemouth (id: 1059) 
- - - - etc 
- - - - etc 

L'API è impostato in modo tale che mi passa un id e restituisce una semplice matrice JSON dei bambini (solo) di quel nodo. Così, per esempio io chiamo: http://www.example.com/api/contentNodes/?parentId=1053 e restituisce:

[ 
    {"Id":1054,"Name":"Rugby League","HasChildren":true}, 
    {"Id":1056,"Name":"Football","HasChildren":true} 
] 

(HasChildren rappresenta se il nodo ha nodi figlio.)

nota, perché i dati-set finirà per essere grande voglio "Carica" ​​più dati dall'API progressivamente mentre i rami dell'albero vengono aperti, piuttosto che scaricare l'intero set di dati e visualizzarlo nella mia app.

Ho creato un 2 App angolare che può essere visto qui: http://plnkr.co/edit/QQ1OKCbd4pDptpSVbWch?p=preview

Il componente chiave è il/file `app content-list.component.ts':

import {Component, OnInit} from 'angular2/core'; 
import {ContentNode}  from './content-node'; 
import {ContentService}  from './content.service'; 

@Component({ 
    selector: 'content-list', 
    template: ` 
     <ol class="tree"> 
      <li *ngFor="#contentNode of contentNodes" class="tree__branch" [ngClass]="{'tree__branch--has-children': contentNode.HasChildren}"> 
       <a *ngIf="contentNode.HasChildren" (click)="toggleBranch(contentNode.Id)" class="toggle">+</a> {{ contentNode.Name }} 
      </li> 
     </ol> 
     <div class="error" *ngIf="errorMessage">{{errorMessage}}</div> 
    ` 
}) 
export class ContentListComponent implements OnInit { 

    constructor (private _contentService: ContentService) {} 

    errorMessage: string; 
    private _startNodeId: number = 1053; 

    contentNodes: ContentNode[]; 

    ngOnInit() { 
     this.getContentNodes(); 
    } 

    getContentNodes() { 
     this._contentService.getContentNodes(this._startNodeId) 
      .subscribe(
       contentNodes => this.contentNodes = contentNodes, 
       error => this.errorMessage = <any>error 
      ); 
    } 

    toggleBranch(branchId:number){ 
     console.log('branchId: ' + branchId); 
    } 
} 

È vedrò qui che sto chiamando il mio servizio che restituisce il JSON come sopra, essendo passato un genitore di 1053.

Ora ho colpito un muro nel riuscire a caricare progressivamente i nodi figli della vista ad albero quando il pulsante + viene cliccato, nell'H annidato Elenco TML (<ol>).

Quale sarebbe l'approccio migliore qui, per ottenere questo in un modo davvero accurato?

Il mio prossimo passo sarà quello di garantire che l'app non comporti eccessive chiamate API, ma la mia preoccupazione immediata è solo quella di ottenere una vista ad albero in esecuzione collegata e funzionante.

Ho visto this example of a recursive treeview ma sembra (a) un po 'buggato (nel senso che ci sono elementi vuoti <ol></ol> resi nell'HTML quando i nodi figli sono vuoti ecc.); e (b) sembra essere impostato in un modo molto "hard-coded" e non ho esperienza sufficiente per rifattenerlo con sicurezza.

Molte grazie.

Nota, per motivi di sicurezza non riesco ad aprire l'API alle richieste pubbliche sfortunatamente, il che rende difficile testare questo su Plunkr, mi rendo conto. Per il momento il mio esempio utilizza solo un set di dati JSON statici a livello singolo.

risposta

8

in Angular2 è possibile rendere le direttive in modo ricorsivo. Questo rende il rendering dell'albero molto facile. Ho modificato il tuo Plunker un po 'solo per mostrare il punto. Non è l'implementazione ideale ma funziona come previsto :).

Esempio:

@Component({ 
    selector: 'tree-view', 
    template: ` 
     <div *ngFor="#dir of dirs"> 
      <tree-view [dirs]="dir.dirs"></tree-view> 
     <div> 
    `, 
    directives: [TreeView] 
}) 
export class TreeView { 
    @Input() 
    private dirs: Array<Directory>; 
} 

Spero che vi piaccia.

Cheers!

+0

Bello! Grazie. Sarei molto interessato a sapere quale sarebbe l'implementazione ideale, dato che la mia app si baserà abbastanza su questa logica.Se hai tempo, una spiegazione sarebbe molto apprezzata, ma comunque grazie per la soluzione di lavoro comunque! :) – Dan

+0

sarebbe un caso molto interessante per l'allenamento con changeetection :) –

+0

Prova questo angular.treeview (https://github.com/eu81273/angular.treeview) – Sankar