2016-07-20 1 views
0

J'essaie d'implémenter un composant de vue arborescente. Ce composant s'utilise récursivement. Je l'ai obtenu pour fonctionner correctement et afficher tous les répertoires et sous-répertoires.Observable ne fonctionne pas correctement dans les composants AngularJS2 imbriqués

Le problème auquel je suis confronté concerne les événements (élément sélectionné). Tous les composants de l'arborescence s'abonnent à l'événement de service partagé, tout comme le composant de base.

Lorsque je débogue le code, je peux voir qu'à tout moment, le service a seulement 1 écouteur à l'événement, ce qui est faux. Le composant de base ne reçoit aucun rappel, ainsi que d'autres problèmes.

En cliquant sur un répertoire, je peux voir à l'intérieur du service partagé que le nombre d'auditeurs est mal réglé à 1.

Edit: Je peux voir que le constructeur de TreeViewService est appelé 4 fois (au lieu de 1).

utilisant AngularJS 2.0.0-RC.2

Voici le code.


TreeViewComponent

export class TreeViewComponent { 
    @Input('items') items: TreeViewItem[] = []; 
    @Input('item') item: TreeViewItem = new TreeViewItem(); 

    constructor(private treeViewService: TreeViewService) { 
    let me = this; 
    this.treeViewService.on('itemSelected', function(item) { 
     me.item = item; 
    }); 
    } 

    treeViewItemSelected(item: TreeViewItem) { 
    this.treeViewService.broadcast('itemSelected', item); 
    } 

treeview.component.html

<ul class="treeview"> 
 
    <li *ngFor="let selItem of items"> 
 
    <a [class.file]="selItem.children.length == 0" [class.folder]="selItem.children.length > 0" [class.selected]="selItem.id == item.id" (click)="treeViewItemSelected(selItem)">{{selItem.title}}</a> 
 
    <my-treeview [items]="selItem.children" *ngIf="selItem.children.length > 0"></my-treeview> 
 
    </li> 
 
</ul>

TreeViewService

import {Injectable} from '@angular/core'; 
import * as Rx from 'rxjs/Rx'; 

@Injectable() 
export class TreeViewService { 

    private listeners:any; 
    private eventSubject: any; 
    private events: any; 

    constructor(){ 
    this.listeners = {}; 
    this.eventSubject = new Rx.Subject(); 
    this.events = Rx.Observable.from(this.eventSubject); 

    this.events.subscribe(
     ({name, args}) => { 
     if(this.listeners[name]) { 
      for(let listener of this.listeners[name]) { 
      listener(...args); 
      } 
     } 
     } 
    ); 
    } 

    on(name, listener) { 
    if(!this.listeners[name]) { 
     this.listeners[name] = []; 
    } 

    this.listeners[name].push(listener); 
    } 

    broadcast(name, ...args) { 
    this.eventSubject.next({ 
     name, 
     args 
    }); 
    } 
} 

BaseComponent

@Component({ 
    selector: 'my-article-form', 
    template: require('./articleform.component.html'), 
    styles: [require('./articleform.component.scss')], 
    providers: [FileUploadService, TreeViewService], 
    directives: [FileManagerComponent, TreeViewComponent] 
}) 
. 
. 
. 

    constructor(private fileUploadService:FileUploadService, private apiService:ApiService, private treeViewService:TreeViewService) { 
    let me = this; 
    this.treeViewService.on('itemSelected', function(item) { 
     me.treeViewItem = item; 
    }); 
    } 

BaseComponent html

Selected: {{treeViewItem.title}}<br /> 
<my-treeview [items]="treeViewItems"></my-treeview> 
+0

Où fournissez-vous le 'TreeViewService'. Si vous le fournissez à 'TreeViewComponent', chaque composant aura sa propre instance. Vous devez le fournir à un parent. –

+0

TreeViewService est fourni dans le tableau des fournisseurs du composant de base. C'est le composant racine. Il est également fourni dans le composant TreeViewComponent. – sm0ke21

+0

Je suppose que vous devez utiliser 'share' ou' publish' https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/core/operators/publish.md pour plusieurs abonnés.Je n'utilise pas moi-même les rxjs et je ne connais pas les détails. –

Répondre

1

Le problème est que les services sont instanciés une fois pour chaque composant. Cela fonctionne de manière hiérarchique bottom-up.

Voir la réponse par Günter Zöchbauer ici: AngularJs 2 - multiple instance of service created

service doit être défini lors de bootstrapping l'application et la seule condition dans le composant racine de tous les autres composants enfants qui ont besoin de partager cette même instance de service.