Problem with catching Event Emitter on another Page

Viewed 514

I have an Iconic / Angular App which has a Filter Tab and then A list beneath. The idea is to go and emit an event when user changes the filter and then the List Page catches the emitted event and refreshes the data of the last from the Filter.

Here is the code i use on my Filter Page

export class TabsFilterListComponent implements OnInit {
  filter = '';
  @Input() filters: Array<ITabFilter>;
  @Output() filterSelected: EventEmitter<IActiveTabFilter> = new EventEmitter<IActiveTabFilter>();

  constructor() { }

  ngOnInit(): void {
    console.log(this.filters);
  }

  toggleFilter(filter: ITabFilter) {

    this.filters.forEach(current => {
      if (current.type !== filter.type) {
        current.isOpened = false;
      }
    });
    filter.isOpened = !filter.isOpened;
  }

  optionSelected(selected: IActiveTabFilter, filter: ITabFilter) {
    // make sure not to emit event if filter was not changed
   console.log(selected);
    if (!(filter.selectedOption && filter.selectedOption.value === selected.option.value)) {
      filter.selectedOption = selected.option;
      // emit event
      this.filterSelected.emit(selected);
      console.log('emitted ', selected);
    }
    if (filter) {
      filter.isOpened = false;
    }
  }

How and to what would i subscribe on my list to catch the emit event and how can get the selected value ?

2 Answers

Taking this out of comments so I can show the code. Instead of using emit as you have it, you could create a service that emits an observable with the latest filter that any component can subscribe to.

Warning: This is not tested code.

This service uses an rxjs Subject which will emit the latest value to the subscriber. You subscribe to the observable 'filter' and call the method setFilter to set the value.

import { Injectable } from '@angular/core';
import { Subject } from 'rxjs';

@Injectable({
  providedIn: 'root'
})
export class FilterService {
  private _filter = new Subject<ITabFilter>();
  filter = this._fiter.asObservable();

  constructor() { }

  public setFilter(filter: ITabFilter): void {
    this._filter.next(filter);
  }
}

You call setFilter like this wherever part of your code knows the latest filter.

...
filter: ITabFilter;

...
constructor(private filterSvc: FilterService) {}

...
this.filterSvc.setFilter(this.filter)

And then where the filter data is needed, you could subscribe to the observable like this

filter: ITabFilter;

constructor(private filterSvc: FilterService) {}
...

this.filterSvc.filter
.subscribe(filter => {
  this.filter = filter;
}, (error) => {
  console.log(error);
});

As you did not show the HTML in your parent component, I can't be sure what your issue is as this is where you make the connection between your emitted event and a method in your parent component. I would expect the parent component HTML to look something like this:

<child-component-selector
  [filters]="filterFromParent"
  (filterSelected)="refreshData($event)">
</child-component-selector>

(filterSelected)="refreshData($event)" connects your @Output, filterSelected, from the child with a method in the parent component I called refreshData. $event will contain your IActiveTabFilter object which you can use to refresh the data.

Related