How to stop the *ngFor directive to re-render the DOM without using 'trackBy'

67 Views Asked by At

I have an observable dictionary as a data-source. Its content is rendered using the ngCompontentOutlet:

<ng-container
*ngFor="let data of dataDictionary$ | async | keyvalue">
<ng-container
  *ngComponentOutlet="
    componentMap[data.value.type];
    injector: this.createInjector(data.value)
  "></ng-container>
</ng-container>

The problem now is, that some of the components templates are using <mat-radio-group> and <mat-expansion-panel>, and by interacting with the radio-buttons for example the whole *ngFor directive is triggered again (almost certain due to the changeDetection) and the parent component re-renders itself and therefore resets the state for the component and the radio buttons. The mat-expansion-panel even triggers this behavior without any interaction, all by itself every second.

My assumption is that the Angular Material Components trigger the change-detection by themselves and therefore ignore the ChangeDetectionStragey.OnPush from their parent components (as seen in Line 86) and as a result the *ngForis triggered.

However, usually I use the trackBy function to control when ngFor should re-render. This is not possible in this case as it iterates over <ng-container>and this constellation does not support the trackBy function. How can I still tell it to only re-render if the data-source changes, not whenever the change-detection is triggered?

EDIT: TrackBy "works" in this constellation if the wrapping ng-container is replaced with a div, but the problem still remains. Even if the TrackBy function returns the same value all the time, the whole thing re-renders with the mat-expansion-panel in a Template. Is the ngForCheck still triggered by the changeDetection, even when trackBy is used?

0

There are 0 best solutions below