0

I'm using ng-select custom server-side search to load data, whether the user provided a search term or not.

component.html

<ng-select [items]="filterValues$ | async"
    [typeahead]="filterValuesInput$"
    [multiple]="true"
    (open)="getFilterValues(pref.id)"
    [loading]="filterValuesLoading"
    bindLabel="name"
    [(ngModel)]="filter_values">
</ng-select>

component.ts

getFilterValues(filterName) {
    this.filterValues$ = concat(
      of([]), // default items
      this.filterValuesInput$.pipe(
        startWith([]),
        distinctUntilChanged(),
        tap(() => this.filterValuesLoading = true),
        switchMap(term => this.preferencesService.getFilterValues(filterName, '' + term).pipe(
          map(res => res.filter_values),
          catchError(() => of([])), // empty list on error
          tap(() => this.filterValuesLoading = false)
        ))
      )
    );
}

The problem I noticed is that whenever I open the select dropdown, it triggers a console error:

Error: ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value: 'loading: false'. Current value: 'loading: true'.

After that the loading spinner triggered by this.filterValuesLoading works fine if a search term is provided. What is the problem here? Thanks!

shAkur
  • 944
  • 2
  • 21
  • 45

2 Answers2

0

It is happening because you are changing the value of filterValues$ on open, which shouldn't be the case, you need to define filterValues$ once, you don't need to do it on each open, I think you can get rid off that function, and initiate your filterValues$ once. Ideally I would define a property filterValues$ and assign the value once only, during init example here, check the loadPeople function, called once, during on init, and they don't use open event emitter at all.

Munzer
  • 2,216
  • 2
  • 18
  • 25
  • I have multiple dropdown selects in the page and I need to know for which filter I am initiating the ``filterValues$``. Also I need to populate each dropdown with a list of results whenever the user clicks a dropdown and not when he types at least 2 characters. That's why I'm using the (open) method – shAkur May 04 '20 at 05:21
0

I managed to get rid of the error. this.filterValuesLoading and this.filterValuesInput$ were initialized using ngOnInit lifecycle hook, however using tap(() => this.filterValuesLoading = true) caused the error I described in the first post. I removed that line and put this.filterValuesLoading = true at the beginning of getFilterValues() method.

I'm open for other suggestions since I don't think this is the best approach

shAkur
  • 944
  • 2
  • 21
  • 45