Reputation: 581
I am trying to implement a tree view component. This component uses itself recursively. I have gotten it to work properly and display all directories and subdirectories.
The problem i am facing is when dealing with events (item selected). All tree view components subscribe to the shared service event, as does the base component.
When i debug the code, i can see that at any given time, the service only has 1 listener to the event, which is wrong. This causes the base component to not receive any callbacks, as well as some other problems.
When clicking on a directory, i can see inside the shared service that the number of listeners is incorrectly set to 1.
Edit: I can see that the TreeViewService's constructor is called 4 times (instead of 1).
using AngularJS 2.0.0-rc.2
Here is the 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>
Upvotes: 0
Views: 255
Reputation: 581
The issue is that Services are instantiated once for every component. This works in a hierarchical manner bottom-up.
See answer by Günter Zöchbauer here: AngularJs 2 - multiple instance of service created
Service needs to be defined when bootstrapping the application and the only provided in the root component of all the other child components that need to share this same service instance.
Upvotes: 2