Angular2 - Interaction between components using a service
Shared service is a common way of communication between non-related components. Your components need to use a single instance of the service, so make sure it's provided at the root level.
An example using the BehaviorSubject as a data delegate:
Shared service:
@Injectable()
export class SharedService {
isVisibleSource: BehaviorSubject<boolean> = new BehaviorSubject(false);
constructor() { }
}
Component 1:
export class Component1 {
isVisible = false;
constructor(private sharedService: SharedService) { }
onClick(): void {
this.isVisible = !this.isVisible;
this.sharedService.isVisibleSource.next(this.isVisible);
}
}
Component 2:
export class Component2 {
constructor(private sharedService: SharedService) { }
ngOnInit(): void {
this.sharedService.isVisibleSource.subscribe((isVisible) => {
console.log('isVisible: ', isVisible); // => true/false
});
}
}
It is worth mentioning that BehaviorSubject
upon a subscription returns the last value it holds, therefore the component from the example above will be updated with the most recent value immediately after the instantiation.
BehaviorSubject
also allows to get its most recent value without even subscribing to it:
this.sharedService.isVisibleSource.getValue(); // => true/false
LHIOUI
Fullstack javascript engineer experienced on multiple frameworks (reactjs/angular 2-4-5 and 6, nodejs) and mobile applications developer(react-native and native apps). Enthusiastic and collaborative team member always willing to take any tasks to achieve success.
Updated on June 26, 2022Comments
-
LHIOUI almost 2 years
I have two component A and B, where component A contains a button. I wish when user click on this button, fire a function on component B
<A></A> <router-outlet></router-outlet>
And the component B is rendered using routing.I am considering using a service with an observable boolean that indicate if the button in A is clicked. Is this the right way to achieve it ?
-
foufrix almost 7 yearsThanks for this, very clean and work out of the box in angular 4 don't forget to import : import {BehaviorSubject} from 'rxjs/BehaviorSubject'; in the service file. Helped me a lot !
-
Shashank Gaurav almost 7 yearsBut this documentation you posted: angular.io/docs/ts/latest/cookbook/… talks explicitly about 'Parent and children communicate via a service' and not sibling to sibling!.. What if I want something like sibling to sibling communication.. Ex: If A and B are two siblings at same node level..Updating something in A via B and same updating something in B via A..
-
Maxime Gélinas almost 7 years@ShashankGaurav the documented example show a communication between a parent and a children, but this relationship is not necessary. A service can establish a communication between 2 or more compconents no matter their relationship. See the accepted answer.
-
Skywalker over 6 yearsHi Seidme I've tried using the technique you explained above but I keep getting the
Expression has changed after it was checked. Previous value: true. Current Value: false
error. Do you know what could be causing this? -
seidme over 6 yearsHi Skywalker, are you using this approach for parent-child component communication? If yes, then the problem might be there, this approach is intended for communication between non-related components Can you please provide plunker? Also, take a look at: stackoverflow.com/questions/34364880/…
-
Skywalker over 6 years@seidme thank you so much for replying. Its not for the parent child approach. Its more of a sibling communication (components of different modules communicating with each other). The only way I could fix the issue was by placing the
subscribe
and the call to theobservable
in the componentsconstructor
. Im not sure whether thats correct approach. Here's the plunkr. To see the error check the browser console. When the app loads a boolean value oftrue
should be displayed but I get the error in the console. -
seidme over 6 years@Skywalker, As can be seen from the plunkr provided, you're using
Subject
instead ofBehaviorSubject
, there is difference in behaving between the two. Try usingBehaviorSubject
as demonstrated in the answer and see if error persists. Please check: stackoverflow.com/questions/39494058/… -
Skywalker over 6 years@seidme I have actually tried the
BehaviourSubject
but unfortunately it gives the same error. I can't seem to figure this out. I've tried almost everything I can find on the net. -
seidme over 6 years@Skywalker Interesting, I'm using this implementation across my all projects and didn't encounter such issues. Will try to investigate what's causing your problem.
-
Skywalker over 6 years@seidme thank you so much for your help! I really appreciate it! I've opened up a question here and any help will be greatly appreciated!
-
LHIOUI about 4 yearsThanks for your answer, but can you explain why angular services shouldn't be stateful? I know that they are often stateless but there is no documentation stating that they should be
-
Wildhammer about 4 yearsService is not an Angular term, it's a paradigm in software engineering that Angular uses. Services contain the repeated business logic that does not belong to a certain component (sharing data is not business logic rather a workaround to overcome a programming issue). If you want your service to save its output then you should inject persistence (local storage, db, apollo, etc.) as context to that service. Besides, this variable in your shared service is accessible to any piece of your application without any hierarchical constraints, very similar to global variable pattern.