Indeed, the best approach will be that of service. Before giving you a sample code, I would like you to be careful on one point.
A component should not have a "business code".
From this information, it is easier to architect its application. This famous "business code" will therefore be contained in a service.
Know that observables can help you!
import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs';
@Injectable({
providedIn: 'root'
})
export class BusinessService
{
public mySharedData$: BehaviorSubject<Date> = new BehaviorSubject<Date>(new Date());
}
This service makes it possible to contain logic, business information and to make it possible to synchronize several components which are not parent / child.
It is important to note that this service is a singleton. You should not add it in the providers table of a module. If you do this, know that each component will have its own instance of this service and the result will not be there!
Component A:
import { Component, OnDestroy, OnInit } from '@angular/core';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { BusinessService } from './../business.service';
@Component({
selector: 'app-component-a',
templateUrl: './component-a.component.html',
styleUrls: ['./component-a.component.css']
})
export class ComponentAComponent implements OnInit, OnDestroy
{
public data: Date;
private _destroy$: Subject<boolean> = new Subject<boolean>();
public constructor(
private _businessService: BusinessService
) { }
public ngOnInit(): void
{
this._businessService
.mySharedData$
.pipe(takeUntil(this._destroy$))
.subscribe(value => this.data = value);
}
public ngOnDestroy(): void
{
this._destroy$.next(true);
this._destroy$.complete();
}
}
Component B:
import { Component, OnDestroy, OnInit } from '@angular/core';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { BusinessService } from './../business.service';
@Component({
selector: 'app-component-b',
templateUrl: './component-b.component.html',
styleUrls: ['./component-b.component.css']
})
export class ComponentBComponent implements OnInit, OnDestroy
{
public data: Date;
private _destroy$: Subject<boolean> = new Subject<boolean>();
public constructor(
private _businessService: BusinessService
) { }
public ngOnInit(): void
{
this._businessService
.mySharedData$
.pipe(takeUntil(this._destroy$))
.subscribe(value => this.data = value);
}
public ngOnDestroy(): void
{
this._destroy$.next(true);
this._destroy$.complete();
}
}
This is the code for component A and B. We inject the BusinessService into the various components and we subscribe to the value changes of the mySharedData property present in the BusinessService via the ngOnInit method.
The mechanism is as follows:
- The service is in memory at the time of injection
- The service values the mySharedData property with today's date and notifies the subscribers of the change (The different components).
- The different components receive the update and process the data as they want.
At this point, you can synchronize a value between several components. You still have to understand the update mechanism. Indeed, you would for example want to update this value from a component.
Let's modify the code of component B a bit:
import { Component, OnDestroy, OnInit } from '@angular/core';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { BusinessService } from './../business.service';
@Component({
selector: 'app-component-b',
templateUrl: './component-b.component.html',
styleUrls: ['./component-b.component.css']
})
export class ComponentBComponent implements OnInit, OnDestroy
{
public data: Date;
private _destroy$: Subject<boolean> = new Subject<boolean>();
public constructor(
private _businessService: BusinessService
) { }
public ngOnInit(): void
{
this._businessService
.mySharedData$
.pipe(takeUntil(this._destroy$))
.subscribe(value => this.data = value);
}
public ngOnDestroy(): void
{
this._destroy$.next(true);
this._destroy$.complete();
}
public updateData(): void
{
this._businessService
.mySharedData$
.next(new Date());
}
}
That's all !
A new value will be pushed into the service and the different components will be notified of the change.
I give you a concept, it's up to you to work on it. Note that it is possible to use the async pipe to directly manage the subscription to mySharedData in your component templates.
I remain of course available if you have any questions and / or comments.
Note: To have a clean code, I advise you to clean the subscriptions to the destruction of the component. I gave you an example along these lines to give you ideas. (_destroy$ + pipe + takeUntil + ngOnDestroy).
See you soon and good luck!