So let's say you have an interface that has a toolbar, sidebar, and a grid. The toolbar has a drop-down that when a user changes, the content in sidebar and grid changes. Back in Angular 1, I would use a Service to have all of my dynamic data. When something changes in the service, all components that use that service will update as well.
Well in Angular 2, it looks like people are using different methods. I wanted to get your input on which is the preferred way.
- Static Service
- OnChanges
- Inputs and Outputs
The remaining question that I have is if it's best practice to create a new service for each data item that is shared between components or can we just have one service that has an object that stores all shared data.
Original Plunker - Each change will have its own service
app.component.ts
import {Component} from 'angular2/core';
import {NavService} from '../services/NavService';
@Component({
selector: 'obs-comp',
template: `obs component, item: {{item}}`
})
export class ObservingComponent {
item: number;
subscription: any;
constructor(private _navService:NavService) {}
ngOnInit() {
this.item = this._navService.navItem();
this.subscription = this._navService.navChange$.subscribe(
item => this.selectedNavItem(item));
}
selectedNavItem(item: number) {
this.item = item;
}
ngOnDestroy() {
this.subscription.unsubscribe();
}
}
@Component({
selector: 'my-nav',
template:`
<div class="nav-item" (click)="selectedNavItem(1)">nav 1 (click me)</div>
<div class="nav-item" (click)="selectedNavItem(2)">nav 2 (click me)</div>
`,
})
export class Navigation {
item = 1;
constructor(private _navService:NavService) {}
selectedNavItem(item: number) {
console.log('selected nav item ' + item);
this._navService.changeNav(item);
}
}
@Component({
selector: 'my-app',
template: `{{title}}
<p>
<my-nav></my-nav>
<button (click)="showObsComp = !showObsComp">toggle ObservingComponent</button>
<div *ngIf='showObsComp'>
<obs-comp></obs-comp>
</div>
`,
directives: [Navigation, ObservingComponent]
})
export class AppComponent {
title = "Angular 2 - event delegation";
showObsComp = true;
constructor() { console.clear(); }
}
NavService.ts:
import {Observable} from 'rxjs/Observable';
import 'rxjs/add/operator/share';
export class NavService {
private _navItem = 0;
navChange$: Observable<number>;
private _observer: Observer;
constructor() {
this.navChange$ = new Observable(observer =>
this._observer = observer).share();
// share() allows multiple subscribers
}
changeNav(number) {
this._navItem = number;
this._observer.next(number);
}
navItem() {
return this._navItem;
}
}
index.html
<!DOCTYPE html>
<html>
<head>
<title>User Input</title>
<link rel="stylesheet" href="styles.css">
<script src="https://code.angularjs.org/2.0.0-beta.11/angular2-polyfills.js"></script>
<script src="https://code.angularjs.org/tools/system.js"></script>
<script src="https://code.angularjs.org/tools/typescript.js"></script>
<script src="https://code.angularjs.org/2.0.0-beta.11/Rx.js"></script>
<script src="https://code.angularjs.org/2.0.0-beta.11/angular2.dev.js"></script>
<script>
System.config({
transpiler: 'typescript',
typescriptOptions: { emitDecoratorMetadata: true },
packages: {
app: {defaultExtension: 'ts'},
services: {defaultExtension: 'ts'},
}
});
System.import('app/boot')
.then(null, console.error.bind(console));
</script>
</head>
<body>
<my-app>Loading...</my-app>
</body>
</html>
app/boot.ts
import {bootstrap} from 'angular2/platform/browser';
import {AppComponent} from './app.component';
import {NavService} from '../services/NavService';
bootstrap(AppComponent, [NavService]);
Revised Plunker for example - Only one service which stores all data in object. A type will be passed to each listener to check if it needs to do anything based on that type.