Issue
Given a custom table component as well as a custom select box component, I want to be able to filter the table rows by selecting an option from the select box.
My idea was to first add a click-listener to the options of my select box, so when clicking on an option, the onOptionClicked()
method will be executed. Inside this onOptionClicked()
method, I will emit an optionSelected
event:
@Output() optionSelected = new EventEmitter<string>();
onOptionClicked(option: string) {
this.optionSelected.emit(option);
}
My table component will react upon the event optionSelected
:
<div class="tbl" (optionSelected)="filterTableRows($event)">
<table>
<thead>
...
There seems to be something fundamentally wrong with this idea, however:
-
My IDE shows an error saying
Event optionSelected is not emitted by any applicable directives nor by div element
. -
The table does not react on the optionSelected event.
It seems the issue is that my table component and my select-box component are different components, apparently they cannot communicate via event emitters. Can someone help me out, please?
Solution
I think there is a misunderstanding on the use of the @Output()
decorator. This is something to be used to emit signals to other components using this one. You seem to be using it in the same component.
Instead, use a ReplaySubject to retain your filter:
optionSelected$ = new ReplaySubject<string>('');
onOptionClicked(option: string) {
this.optionSelected$.next(option);
}
To do the data filtering you could subscribe to the replay subject:
this.optionSelected$.subscribe(filter => {
this.yourFilteredData = this.yourData.filter(item => {
// <-- you filter code
});
})
Note: please remember to complete any subscriptions when the component is destroyed to avoid the common memory leak.
Answered By – The Fabio
Answer Checked By – Terry (AngularFixing Volunteer)