2016-07-20 33 views
0

Ich versuche, eine Strukturansicht-Komponente zu implementieren. Diese Komponente verwendet sich selbst rekursiv. Ich habe es richtig funktionieren lassen und alle Verzeichnisse und Unterverzeichnisse anzeigen lassen.Observable funktioniert nicht ordnungsgemäß in geschachtelten AngularJS2-Komponenten

Das Problem, mit dem ich konfrontiert bin, ist im Umgang mit Ereignissen (Element ausgewählt). Alle Strukturansichtskomponenten abonnieren das Shared-Service-Ereignis ebenso wie die Basiskomponente.

Wenn ich den Code debuggen, kann ich sehen, dass der Dienst nur 1 Listener für das Ereignis hat, was falsch ist. Dies führt dazu, dass die Basiskomponente keine Rückrufe sowie einige andere Probleme erhält.

Wenn auf einem Verzeichnis klicken, i innerhalb des Shared-Service, der die Anzahl der Zuhörer auf 1

bearbeiten ist falsch eingestellt zu sehen: ich, dass der Konstruktor des TreeViewService sehen kann 4 mal aufgerufen wird (statt 1).

mit AngularJS 2.0.0-rc.2

Hier ist der 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

Wo stellen Sie den 'TreeViewService' bereit. Wenn Sie es bei der 'TreeViewComponent' bereitstellen, erhält jede Komponente ihre eigene Instanz. Sie müssen es bei einem Elternteil angeben. –

+0

Der TreeViewService wird im Provider-Array der Basiskomponente bereitgestellt. Dies ist die Wurzelkomponente. Es wird auch in der TreeViewComponent-Komponente bereitgestellt. – sm0ke21

+0

Ich denke, Sie müssen 'share' oder' publish' https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/core/operators/publish.md für mehrere Abonnenten verwenden.Ich benutze Rxjs nicht selbst und kenne keine Details. –

Antwort

1

Das Problem ist, dass Dienstleistungen einmal für jede Komponente instanziiert werden. Dies funktioniert hierarchisch von unten nach oben.

Siehe Antwort von Günter Zöchbauer hier: AngularJs 2 - multiple instance of service created

Dienst muss definiert werden, wenn die Anwendung Bootstrapping und die einzigen in der Wurzelkomponente aller anderen untergeordneten Komponenten zur Verfügung gestellt, die die gleiche Service-Instanz teilen müssen.