Passing data or invoking methods between sibling component
When passing data between components, I find the RxJS `BehaviorSubject` very useful.
You can also use a regular RxJS Subject
for sharing data via a service, but here’s why I prefer a BehaviorSubject.
- It will always return the current value on subscription - there is no need to call onNext().
- It has a getValue() function to extract the last value as raw data.
- It ensures that the component always receives the most recent data.
- you can get an observable from behavior subject using the
asObservable()
method on behavior subject.
- Refer this for more
Example
In a service, we will create a private BehaviorSubject that will hold the current value of the message. We define a currentMessage variable to handle this data stream as an observable that will be used by other components. Lastly, we create the function that calls next on the BehaviorSubject
to change its value.
The parent, child, and sibling components all receive the same treatment. We inject the DataService in the components, then subscribe to the currentMessage observable and set its value equal to the message variable.
Now if we create a function in any one of these components that changes the value of the message. The updated value is automatically broadcasted to all other components.
shared.service.ts
import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs';
@Injectable()
export class SharedService {
private eventSource = new BehaviorSubject<string>("default message");
eventSubject = this.eventSource.asObservable();
constructor() { }
emitEvent(value: string) {
this.eventSource.next(value)
}
}
sibling.component.ts
import { Component, OnInit } from '@angular/core';
import { DataService } from "../data.service";
@Component({
selector: 'app-sibling1',
template: `
{{message}}
`,
styleUrls: ['./parent.component.css']
})
export class SiblingComponent1 implements OnInit {
message: string;
constructor(private data: DataService) { }
ngOnInit() {
this.data.eventSubject.subscribe(value => this.showValues(value));
}
}
sibling.component.ts
import { Component, OnInit } from '@angular/core';
import { SharedService } from "../shared.service";
@Component({
selector: 'app-sibling2',
template: `
{{message}}
<button (click)="emitEvent()">New Message</button>
`,
styleUrls: ['./sibling2.component.css']
})
export class SiblingComponent2 implements OnInit {
message: string;
constructor(private service: SharedService) { }
// emit value in oninit
ngOnInit() {
this.service.emitEvent("Hello from Sibling-1");
}
// emit value on event
emitEvent() {
this.service.emitEvent("Hello from Sibling");
}
}
Why use Service ?
Angular distinguishes components from services in order to increase modularity and reusability.
and It's Good Practice to Delegate complex component logic to services
From Angular Style Guide
Do limit logic in a component to only
that required for the view. All other logic should be delegated to
services.
Do move reusable logic to services and keep components simple and
focused on their intended purpose.
Why? Logic may be reused by multiple components when placed within a
service and exposed via a function.
Why? Logic in a service can more easily be isolated in a unit test,
while the calling logic in the component can be easily mocked.
Why? Removes dependencies and hides implementation details from the
component.
Why? Keeps the component slim, trim, and focused.
Usage of Services In Angular also ensures that you are not violating DRY and SRP principles of software development,For your scenario the best solution is to use a service