2016-07-20 6 views
0

Я пытаюсь реализовать компонент дерева. Этот компонент использует себя рекурсивно. Я получил его для правильной работы и отображения всех каталогов и подкаталогов.Замечание не работает правильно в вложенных компонентах AngularJS2

Проблема, с которой я столкнулся, - это дело с событиями (выбранный предмет). Все компоненты дерева представлений подписываются на общее событие службы, равно как и базовый компонент.

Когда я отлаживаю код, я вижу, что в любой момент времени сервис имеет только 1 прослушиватель события, что неверно. Это приводит к тому, что базовый компонент не получает никаких обратных вызовов, а также некоторых других проблем.

При нажатии на каталог, я могу видеть в общей службы, что количество слушателей неправильно установлен в 1.

Edit: я могу видеть, что конструктор TreeViewService, называется 4 раза (вместо 1).

с использованием AngularJS 2.0.0-РК-2

Вот код.


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

Где вы указываете "TreeViewService". Если вы предоставите его в «TreeViewComponent», каждый компонент получит свой собственный экземпляр. Вы должны предоставить его у родителя. –

+0

TreeViewService предоставляется внутри базы поставщиков базового компонента. Это корневой компонент. Он также предоставляется внутри компонента TreeViewComponent. – sm0ke21

+0

Я думаю, вам нужно использовать 'share' или' publish' https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/core/operators/publish.md для нескольких подписчиков.Я сам не использую rxjs и не знаю деталей. –

ответ

1

Вопрос заключается в том, что услуги инстанцируются один раз для каждого компонента. Это работает иерархически снизу вверх.

См ответ Гюнтера Zöchbauer здесь: AngularJs 2 - multiple instance of service created

служба должна быть определена, когда развернув приложение и предоставляется только в корневой компонент всех остальных дочерних компонентов, которые необходимо разделить этот же экземпляр службы.