Reputation: 267
I have two components in my Angular 4 application, say listComponent & searchComponent which have no relations. I want to invoke a function in listComponent while a search criterion is selected from searchComponent. Which is the best and efficient way to do this considering the performance as well?
Either:
1) I can pass output events to root and do the data changes using a data service, i.e., switch the component displaying and get the data from a common service. Here I have to call ngAfterViewChecked() or ngOnChange() every time and use some flags to get to know new Search is selected from searchComponent .
2) Using a rxjs/behavioralSubject in data service and set it from searchComponent and subscribe it in listComponent.
Upvotes: 0
Views: 3764
Reputation: 694
I think the best solution is using ngrx. Im use this few times and it idealy fit to problem like this.
Upvotes: 0
Reputation: 34455
I usually use a service with subjects
import {Injectable} from '@angular/core';
import {Observable, Subject} from "rxjs";
/**
* Event Types
*/
export const MyAppEventTypes =
{
EventType1: 'EventType1'
//...
};
/**
* Events
*/
export class MyAppEvent
{
type: string;
data: any;
}
/**
* Service in charge of broadcasting messages
*/
@Injectable()
export class MessageService
{
/**
* Subject to trigger events
* @type {Subject<MyAppEvent>}
*/
private myAppEventSubject: Subject<MyAppEvent> = new Subject<MyAppEvent>();
/**
* The observable for events
* @type {"../../Observable".Observable<MyAppEvent>}
*/
public readonly myAppEvent$: Observable<MyAppEvent> = this.myAppEventSubject.asObservable();
/**
* Broadcasts a message
* @param name
* @param data
*/
broadcast(name: string, data)
{
this.myAppEventSubject.next(
{
type: name,
data: data
});
}
}
Then, in a class that needs to broadcast a message, after injecting the service
this.messageService.broadcast(MyAppEventTypes.EventType1, {data: 'test'});
And in a class that needs to receive the message, after injecting the service
this.messageService.myAppEvent$.subscribe(ev => {
if (ev.type == MyAppEventTypes.EventType1)
{
this.data = ev.data;
}
});
Upvotes: 0
Reputation:
Several solutions :
1 - Use a service. It should contain either Subjects to emit events, or at least data to store the data you set in the two components.
2 - Use Outputs / Inputs from the parent component.
3 - Use a ViewChild component with Outputs. Once the parent component receives an output, it calls a metyhod in the child components via the view child binding.
Upvotes: 1
Reputation: 5889
If there is any parent/child connection between the two components, you should use @Input and @Output.
So i will assume the list component take the search criteria as Input and search component emit an output event once item is selected.
In this way you can update your list component on ngOnChanges() and if you want to not notify the list component unless it's input got changed so use ChangeDetectionStrategy.OnPush.
The second way as you mentioned is using rxjs/behavioralSubject in separate service where you push the search criteria from your search component and subscribe to that subject on your list component.
If there is more search logic you can get the benefits of using services on Angular and create search service that deals with all search logic including notify components.
Upvotes: 1