I've done some reading about sharing a service between components and a the basic idea of using the app component which to my understanding is essentially creating a singleton of the service as a provider.
I load a component which has nested components and the nested components all use this shared service. An event in the future triggers on the page and I now need the HTTP service to update and update all the nested components template elements. How exactly do I "force" this update?
Also, does it mean that because I shared a service in the app component that the HTTP service will run whenever the page "root" component loads?
UPDATE: I didn't have time to put anything together this weekend, but in case things still aren't clear, I made a simplified example to show how service injection works in Angular 2.
The AppComponent lists the AppService as a provider in the @Component decorator, meaning that a singleton of the service is injected at this component level. In the ChildComponent, the service does not need to be listed as a provider because it will use the same instance injected into AppComponent. All it needs to do is import the AppService module, and inject the service in the constructor definiton.
Conversely, the IsolatedComponent uses a separate instance of AppService, so it DOES inject a new singleton instance via the providers array in its @Component decorator. The IsolatedChildComponent will use the same service instance used by the IsolatedComponent, so as with the ChildComponent, all it needs to do is import the AppService module, and inject the instance into its constructor definition.
Notice how each component updates the shared binding property, messages, whenever the component is initialized, and the child component automatically captures these updates. The same logic can be applied to services that make API calls.
Here is the code for the service and components:
app.service.ts
import { Injectable } from '@angular/core';
@Injectable()
export class AppService {
messages: string[] = [];
updateMessages(msg: string) {
this.messages.push(msg);
}
}
app.component.ts
import { Component, OnInit } from '@angular/core';
import { AppService } from './app.service';
import { ChildComponent } from './child.component';
import { IsolatedComponent } from './isolated.component';
@Component({
selector: 'my-app',
template: `
<h1>AppComponent Tree</h1>
<p>
AppComponent and ChildComponent consume the same instance of AppService
</p>
<child-component></child-component>
<hr />
<isolated-component></isolated-component>
`,
providers: [AppService],
directives: [ChildComponent, IsolatedComponent]
})
export class AppComponent implements OnInit {
messages: string[];
constructor(private appService: AppService) {
this.messages = appService.messages;
}
ngOnInit() {
this.addMessage(`AppComponent Initialized`);
}
private addMessage(msg: string) {
this.appService.updateMessages(msg);
}
}
child.component.ts
import { Component, OnInit } from '@angular/core';
import { AppService } from './app.service';
@Component({
selector: 'child-component',
template: `
<div *ngFor="let message of messages">{{message}}</div>
`
})
export class ChildComponent implements OnInit {
messages: string[];
constructor(private appService: AppService) {
this.messages = appService.messages;
}
ngOnInit() {
this.addMessage(`ChildComponent Initialized`);
}
private addMessage(msg: string) {
this.appService.updateMessages(msg);
}
}
isolated.component.ts
import { Component, OnInit } from '@angular/core';
import { AppService } from './app.service';
import { IsolatedChildComponent } from './isolated-child.component';
@Component({
selector: 'isolated-component',
template: `
<h1>Isolated Component Tree</h1>
<p>
IsolatedComponent and IsolatedChildComponent consume an
instance of AppService separate from the AppComponent tree
</p>
<isolated-child></isolated-child>
`,
providers: [AppService],
directives: [IsolatedChildComponent]
})
export class IsolatedComponent implements OnInit {
messages: string[];
constructor(private appService: AppService) {
this.messages = appService.messages;
}
ngOnInit() {
this.addMessage(`IsolatedComponent initialized`);
}
private addMessage(msg: string) {
this.appService.updateMessages(msg);
}
}
isolated-child.component.ts
import { Component, OnInit } from '@angular/core';
import { AppService } from './app.service';
@Component({
selector: 'isolated-child',
template: `
<div *ngFor="let message of messages">{{message}}</div>
`
})
export class IsolatedChildComponent implements OnInit {
messages: string[];
constructor(private appService: AppService) {
this.messages = appService.messages;
}
ngOnInit() {
this.addMessage(`IsolatedChildComponent initialized`);
}
private addMessage(msg: string) {
this.appService.updateMessages(msg);
}
}
See the Hierarchical Injectors documentation.