2016-04-09 27 views
6

Uczę się języka Angular 2, próbując utworzyć rozwijany widok drzewa z (potencjalnie bardzo dużego) interfejsu API innej firmy. API ma podstawową strukturę jak poniżej:Najlepsze podejście do dynamicznego tworzenia rekursywnego widoku drzewa z interfejsu API danych

- 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 

API jest tak nastawiony, aby przekazać identyfikator i zwraca prosty JSON tablicę dzieci (tylko) tego węzła. Tak więc, na przykład zadzwonić: http://www.example.com/api/contentNodes/?parentId=1053 i powraca:

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

(HasChildren reprezentuje czy węzeł ma węzły potomne.)

uwaga, ponieważ zbiór danych ostatecznie będzie duża chcę "pobieraj" więcej danych z API progresywnie w miarę otwierania gałęzi drzewa, zamiast wysypywać cały zestaw danych i renderować go w mojej aplikacji.

Wcześniej skonfigurować aplikację kątowym 2, które można zobaczyć tutaj: http://plnkr.co/edit/QQ1OKCbd4pDptpSVbWch?p=preview

Kluczowym elementem jest aplikacja plik `/ 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); 
    } 
} 

You zobaczę tutaj, że nazywam się moją usługą, która zwraca JSON jak wyżej, przez przekazanie identyfikatora rodzica 1053.

Uderzyłem w ścianę, aby móc stopniowo ładować węzły potomne widoku drzewa, gdy Kliknij przycisk + w zagnieżdżonym H Lista TML (<ol>).

Jakie byłoby najlepsze podejście, aby osiągnąć to w naprawdę czysty sposób?

Następnym krokiem będzie zapewnienie, że aplikacja nie będzie generować nadmiernych wywołań interfejsu API, ale moim bezpośrednim zmartwieniem jest tylko sprawienie, aby działające podglądy drzewa działały.

Widziałem , ale wydaje się (a) trochę buggy (w tym są puste elementy <ol></ol> renderowane w HTML, gdy węzły podrzędne są puste itp); i (b) wydaje się, że jest ustawiony w bardzo "zakodowany" sposób i nie jestem wystarczająco doświadczony, aby pewnie go zmienić.

Wielkie dzięki.

Uwaga, ze względów bezpieczeństwa nie mogę niestety otworzyć API na publiczne prośby, co sprawia, że ​​testowanie tego na Plunkr jest trochę trudne, zdaję sobie z tego sprawę. Na razie mój przykład wykorzystuje tylko statyczny, jednopoziomowy zestaw danych JSON.

Odpowiedz

8

w Angular2 można renderować rekursywnie dyrektywy. To sprawia, że ​​renderowanie drzewa jest bardzo łatwe. Zmodyfikowaliśmy trochę Twój Plunker tylko po to, by pokazać punkt. To nie jest idealna implementacja, ale działa zgodnie z oczekiwaniami :).

Przykład:

@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>; 
} 

Mam nadzieję, że się Wam spodoba.

Pozdrawiam!

+0

Nice! Dzięki. Byłbym bardzo zainteresowany, aby usłyszeć, jaka będzie idealna implementacja, ponieważ moja aplikacja będzie w dużym stopniu opierała się na tej logice.Jeśli będziesz miał czas, wyjaśnienie zostanie bardzo docenione, ale poza tym dzięki za rozwiązanie robocze! :) – Dan

+0

byłby bardzo interesującym przypadkiem do treningu ze zmienioną konfiguracją :) –

+0

Wypróbuj ten angular.treeview (https://github.com/eu81273/angular.treeview) – Sankar