2

I'm trying to filter a list of objects within a mat-dialog popup window. I based my implementation on this very good post to avoid running Angular change detection at every keyUp event.

After implementing my filter, I verified with a console log in ngDoCheck the change detection cycles. It appeared each keyUp event was triggering several change detection cycles.

I figured out what was the difference between the post I took as example and mine : I'm within a Material Dialog component.

I prepared a stackblitz example to show it. The FormComponent is integrated twice, once directly in the AppComponent and once within a mat-dialog. Open your console and watch for the cd and filtering strings, which logs change detection cycles and items filtering respectively. You'll notice that when you use the dialog version, there is a very large number of cd.

Complete code at this address

Is there a way of deactivating the change detections within the mat-dialog ? If yes, what are the side effects ?

The API of MatDialog does not contains anything that seems close to what I'm searching...

Please note that my code does execute properly, but the very high amount of change detection cycles might lower app performances on slower devices.

Hope someone can help !

Edit

Based on comments, I tried to switch ChangeDetectionStrategy to onPush (this should not have any side effect as the binding is performed with the filtered list which is re-assigned after the debounce time). This does however not help.

I also tried to detach my component from the change detection with such code :

ngAfterViewInit() {
  this.ngzone.runOutsideAngular(() => {
    this.filterChangedSubscription = Observable.fromEvent(this.itemfilter.nativeElement, 'keyup')
    .debounceTime(600)
    .subscribe((keyboardEvent: any) => {
      this.items = this.unfilteredItems.filter(
        item => item.toLowerCase().indexOf(keyboardEvent.target.value.toLowerCase()) > -1
      );
      this.cdref.detectChanges();
    });
  });
  this.cdref.detach();
}

I was trying to disable the detection changes for my component (holding the input triggering the filter), but it seems the change detection hooks to be still called several time at each keyUp event.

I suspect mat-dialog component to register itself to keyUp events for accessibility shortcuts and triggering change detection. Feel free to share your thoughts.

Wis
  • 705
  • 1
  • 11
  • 34
  • This might [help](https://blog.angular-university.io/onpush-change-detection-how-it-works/) – Vikas Jun 03 '18 at 08:51
  • Interesting lecture. But setting `OnPush` change detection strategy does not help. The `onDoCheck` lifecycle hook of my component is still called many times at each `keyUp` event. I went further in the lecture by understanding how change detection really works. I tried to use `changeDetectorRef.detach()` with no more success. I suspect the `mat-dialog` to register itself for `keyUp` events, and consequently trigger the change detection in its view children (= my component). I'll update my question with these tentatives to help investigate. – Wis Jun 03 '18 at 15:27
  • 1
    `I suspect the mat-dialog to register itself for keyUp events, and consequently trigger the change detection in its view children` you're right here. It's `OverlayKeyboardDispatcher` – yurzui Jun 03 '18 at 15:46
  • Any chance I can deactivate this `OverlayKeyboardDispatcher` when opening the `mat-dialog` ? – Wis Jun 03 '18 at 16:15
  • Did you find any solutions? – N.F. Jun 03 '21 at 09:50

1 Answers1

0

ngDoCheck() does not guarantee that Change Detection is being run.

https://stackblitz.com/edit/angular-trqwq2?file=src%2Fapp%2Fapp.component.html,src%2Fapp%2Fapp.component.ts

Here I updated your example. By the way: here you can bind outputs in the outer zone:

https://blog.simplified.courses/running-outputs-outside-zonejs-for-angular-performance-optimization/

Hope it helps

Brecht Billiet
  • 235
  • 1
  • 6