I've been at this for some time, many articles, the documentation, much trial and error but I feel I'm missing something core.
Essentially I'm trying to create an extensible navigation component that other components can add items to when they are added to the page. I've tried to accomplish this a couple ways, including a service, this example I'm attempting it by injected one component into another component.
I have a component with a list of items in it, I have an ngFor that loops through the items and displays text. I have a button on the page that when you click adds an item to the array. I also have injected the component into another component that I have add an item to the array on NgOnInit() (tried other lifecycle events and in the constructor).
The strangeness is that when the button adds the items to the array the list updates but when the other component adds the items the list it does not update the UI even though the count of items is incremented and I can see in the UI the component has already loaded and rendered the default items.
import {Component} from 'angular2/core';
import {Router, RouteParams} from 'angular2/router';
import {RouteConfig, ROUTER_DIRECTIVES} from 'angular2/router';
import {Injectable} from 'angular2/core';
@Component({
selector: 'caseBasedSearchSidebar',
template: `<ul id="sidebar-wrapper" class="clearfix nav navbar-default sidebar-nav">
<li *ngFor="#nav of navigationItems">
<span>{{nav.name}}</span>
</li>
<ul> <button (click)=addNavigationItem()>Add</button> `,
directives: [ROUTER_DIRECTIVES] })
@Injectable() export class SidebarComponent {
public navigationItems: Array<ISideNavigationItem>;
constructor() {
this.navigationItems = [{ name: 'test' }];
}
public addNavigationItem(item: ISideNavigationItem) {
this.navigationItems.push({ name: 'test' });
}
}
export interface ISideNavigationItem {
name: string; }
import {Component, OnInit} from 'angular2/core';
import {SidebarComponent} from '../sideBar.component';
@Component({
templateUrl: '/CaseBasedSearch/PatientInformation',
providers: [SidebarComponent]
})
export class PatientInformationComponent implements OnInit {
private sideBarComponent: SidebarComponent;
constructor(sideBarComponent: SidebarComponent) {
this.sideBarComponent = sideBarComponent;
}
ngOnInit() {
this.sideBarComponent.addNavigationItem({ name: 'testing' });
}
}
Any guidance is appreciated.
You are assigning the navigationItems
model inside of your SidebarComponent
. Changes to this model won't propagate to other components.
Consider setting up navigationItems
as an @Input property instead:
@Input() public navigationItems: Array<ISideNavigationItem>;
And passing your model from the parent component (PatientInformationComponent) to your child component (SidebarComponent):
<case-based-search-sidebar [navigationItems]="navigationItems">
Also, as a matter of convention, the selector in your SidebarComponent should be snake-case:
selector: 'case-based-search-sidebar'
As others have mentioned:
Ultimately my problem was scoping of the injected service/component. I was using the providers item on each component and with the service this resulted in each service having it's own instance. When the components updated the service it was not updating the same array which previous tests led me to believe it was. My moving the injection to boot.ts they all began getting the same instance. Answer here.
The final code;
import {Component, OnInit} from 'angular2/core';
import {CaseBasedSearchNavigationService} from '../caseBasedSearchNavigation.service';
import {ISideNavigationItem} from '../caseBasedSearchNavigation.service';
@Component({
templateUrl: '/CaseBasedSearch/PatientInformation'
})
export class PatientInformationComponent implements OnInit {
private navigationService: CaseBasedSearchNavigationService;
constructor(navigationService: CaseBasedSearchNavigationService) {
this.navigationService = navigationService;
this.navigationService.addNavigationItem({ name: 'testing' });
this.navigationService.addNavigationItem({ name: 'testing' });
}
ngOnInit() {
}
}
import {Component, Input} from 'angular2/core';
import {Router, RouteParams} from 'angular2/router';
import {RouteConfig, ROUTER_DIRECTIVES} from 'angular2/router';
import {CaseBasedSearchNavigationService} from './caseBasedSearchNavigation.service';
import {ISideNavigationItem} from './caseBasedSearchNavigation.service';
@Component({
selector: 'case-based-search-sidebar',
template: `<ul id="sidebar-wrapper" class="clearfix nav navbar-default sidebar-nav clearfix">
{{navigationItems.length}}
<li *ngFor="#nav of navigationItems">
<span>{{nav.name}}</span>
</li>
<ul>`,
directives: [ROUTER_DIRECTIVES]
})
export class SidebarComponent {
public navigationItems: ISideNavigationItem[];
constructor(navigationService: CaseBasedSearchNavigationService) {
this.navigationItems = navigationService.navigationItems;
navigationService.addNavigationItem({name : 'test2'});
}
}
import {Injectable} from 'angular2/core';
@Injectable()
export class CaseBasedSearchNavigationService {
public navigationItems: ISideNavigationItem[];
constructor() {
this.navigationItems = [];
}
public addNavigationItem(item: ISideNavigationItem) {
this.navigationItems.push(item);
}
}
export interface ISideNavigationItem {
name : string;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With