3

I have a array with filters:

["BOX_NAMES", "BATHROOMS", "CONFERENCE_HALLS"]

and i show part of view when filter is active in *ngIf* directive like that:

*ngIf="isFilterActive(Filters.CONFERENCE_HALLS)"

isFilterActive function implementation:

if (this.officeService.selectedFilter[0] === Filters.SHOW_ALL) {
    return true;
  }
  return this.officeService.selectedFilter.includes(filter);
}

When i change filter, my view rerender lots of times. How to avoid this?

Of course my components are loaded in lazy loading.

  • Never reference a property on a shared service directly from a template expression. You'll trigger a changed after check error. I'm surprised this hasn't already done that. – Reactgular Dec 27 '19 at 14:26

2 Answers2

4

Firstly: Why is it a problem that your component renders a lot of times? You should not have any performance issues, since *ngIf is designed for those operations.

The reason why your component renders so often because Angular triggers ChangeDetection whenever something changes in your component. Then, all variables, directives in your view are checked if something changed.

What you could do in order to avoid that is to prevent doing that in your component decorator by adding another changeDetectionStrategy like this:

@Component({
    // ...other ocmponent decorator properties
    changeDetection: ChangeDetectionStrategy.OnPush
})

Now your component only triggers changeDetection if your @Input() parameters change, or if you specifically tell it to. So now, whenever you change your filters (or do something else in your component which is not triggered through @Input() parameters, you need to trigger changeDetection manually.

Therefore, first inject it via DependencyInjection in your constructor:

constructor(private cd: ChangeDetectorRef) {}

Then, call it after you executed the change:

this.cd.detectChanges();

Hope that helps.

dave0688
  • 5,372
  • 7
  • 33
  • 64
3

This is caused by the fact that you use a function to evaluate the return value.

If you set the result of this function in a property in your .ts file, and then use this property in your *ngIf, then you won't have the issue. This is caused because Angular doesn't know what value is to be checked, so it calls the function everytime there is a changeDetection triggered.

Here is an example given your sample :

activeFilter;

onFilterChange(event) {
  if (this.officeService.selectedFilter[0] === Filters.SHOW_ALL) {
    this.activeFilter = true;
  }
  this.activeFilter = this.officeService.selectedFilter.includes(filter);
}

*ngIf="activeFilter"

Of course, this is a sample code that needs more thoughts and serves as a mere incomplete example.


You can also improve the way the changeDetection is triggered by using the ChangeDetectionStrategy : OnPush in the decorator of the component so that change detection cycles will only occur when an @Input() in your component has been changed.

Alex Beugnet
  • 4,003
  • 4
  • 23
  • 40