Reputation: 13826
I have a simple structure, with multiple components and a single service [StackBlitz]:
@Injectable()
export class Service {
constructor(private http: HttpClient) {}
post(entity: IEntity): Observable<IEntity> {
return this.http
.post<IEntity>('/api/entity', entity)
.pipe(map(parseDates));
}
get(): Observable<IEntity[]> {
return this.http
.get<IEntity[]>('/api/entity')
.pipe(map(parseDates));
}
}
@Component({
selector: 'app-component0',
template: `<app-component1></app-component1>
<app-component2></app-component2>`,
styleUrls: []
})
export class Component0 {}
@Component({
selector: 'app-component1-create',
template: `<button (click)="submit()">Submit</button>`,
styleUrls: []
})
export class Component1 {
constructor(private service: Service) { }
submit() {
this.service.post({foo: 'bar'})
.subscribe(console.info, console.error)
}
}
@Component({
selector: 'app-component2-table',
template: `<pre>{{ entities | json }}</pre>`,
styleUrls: []
})
export class Component2 implements OnInit {
entities: IEntity[];
constructor(private service: Service) { }
ngOnInit() {
this.service.get()
.subscribe(entities => this.entities = entities,
console.error)
}
}
How do I get Component1
to update Component2
, through the Service
?
Upvotes: 0
Views: 78
Reputation: 7875
you should have another observable to mitigate your component communication :
@Injectable()
export class StoreService {
private _employes$ = new BehaviorSubject<{id:number,employee_name:string,employee_salary:number,employee_age:number}[]>([]);
constructor(private _http: HttpClient) {
this.refresh();
}
refresh() {
this._http.get<{id:number,employee_name:string,employee_salary:number,employee_age:number}[]>('https://dummy.restapiexample.com/api/v1/employees').subscribe(
data => this._employes$.next(data)
);
}
post() {
const payload = {"name":"test","salary":"123","age":"23"};
this._http.post('https://dummy.restapiexample.com/api/v1/create', payload).subscribe(() => {
this.refresh();
})
}
get employes$(): Observable<{id:number,employee_name:string,employee_salary:number,employee_age:number}[]> {
return this._employes$.asObservable();
}
}
Which are compose by two part :
Observable use by your store, when you want to update your stream, you can next to it.
private _employes$ = new BehaviorSubject<{...}[]>([]);
Exposed getter. Any component which need to be inform by any change on your store can subscribe to it.
get employes$(): Observable<{...}[]> {
return this._employes$.asObservable();
}
From now all is relative to your actual case, you have various way to update this internal observable :
the quickest way :
refresh() {
this._http.get<{...}[]>('...').subscribe(
data => this._employes$.next(data)
);
}
Inside your service, you subscribe to your http call and update your internal observable.
Pro :
Con :
Observable gymnastic
If you don't want to subscribe on your service. You can do something like :
return this._http.get<{...}[]>('...')
.pipe(switchMap(result => {
this._employes$.next(result);
return this.employes$;
}));
you transform your http get observable to the internal observable. At the same time you next the new result of your API answer.
If tomorrow you need to delegate a special traitment on the API response before make it available accross your application.
you can do :
refresh(myCustomTraitment: = null) {
return this._http.get<{...}[]>('...')
.pipe(switchMap(result => {
if (myCustomTraitment) {
result = result.map(myCustomTraitment);
}
this._employes$.next(result);
return this._employes$;
}));
}
Upvotes: 1