From the Angular documentation, data can be shared between components by using:
The third example from the documentation shows communication between parent and child so here is an example of two sibling components sharing data via a service. Stackblitz Example
First, set up the service with a BehaviorSubject
. This allows components to push data to and get data from the service.
data.service.ts
import { Injectable } from '@angular/core';
import {of, BehaviorSubject, Observable} from 'rxjs'
@Injectable()
export class DataService {
private _data: BehaviorSubject<any> = new BehaviorSubject<any>(null)
constructor() { }
getData(): Observable<any> {
return this._data.asObservable();
}
setData(data: any) {
this._data.next(data);
}
getSomeData() {
return of([
{id: 1, name: 'Name 1'},
{id: 2, name: 'Name 2'},
{id: 3, name: 'Name 3'},
]);
}
}
Next create a component, in this case first.component
, that has the DataService
injected into it. This component uses both methods of communication, EventEmitter
s with @Output()
s and setting data on the service for other components to subscribe to.
first.component.ts
import { Component, EventEmitter, OnInit, Output } from '@angular/core';
import {DataService} from '../data.service';
@Component({
selector: 'app-first',
templateUrl: './first.component.html',
styleUrls: ['./first.component.css']
})
export class FirstComponent implements OnInit {
@Output() dataLoaded: EventEmitter<any> = new EventEmitter<any>();
constructor(private dataService: DataService) { }
ngOnInit() {
this.dataService.getSomeData().subscribe(
(data: any) => {
// use this to emit data to a parent component
this.dataLoaded.emit(data);
// use this to set data in the service that other components can subscribe to
this.dataService.setData(data);
}
);
}
}
In the AppComponent
, set up a variable data
to hold the data that gets emitted from the FirstComponent
.
app.component.ts
import { Component } from '@angular/core';
@Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: [ './app.component.css' ]
})
export class AppComponent {
private _data: any[] = [];
get data(): any[] {
return this._data;
}
set data(data: any[]) {
this._data = data;
}
}
Then listen for the dataLoaded
event in the app component template and set the app component's data.
app.component.html
<app-first (dataLoaded)="data = $event"></app-first>
To get data to the SecondComponent
, when the FirstComponent
subscribes to data and emits it to its parent component, the FirstComponent
can also send that data back to the service which puts the data into another Observable that the SecondComponent
can subscribe to.
second.component.ts
import { Component, OnInit } from '@angular/core';
import {DataService} from '../data.service';
@Component({
selector: 'app-second',
templateUrl: './second.component.html',
styleUrls: ['./second.component.css']
})
export class SecondComponent implements OnInit {
data: any[] = [];
constructor(private dataService: DataService) { }
ngOnInit() {
this.dataService.getData().subscribe(
(data: any) => this.data = data
);
}
}
The SecondComponent
can now use the data loaded from the FirstComponent
in its template.
second.component.html
<table>
<thead>
<tr>
<th>Id</th>
<th>Name</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let item of data">
<td >{{ item?.id }}</td>
<td >{{ item?.name }}</td>
</tr>
</tbody>
</table>