Below is the template of a parent component:
<ng-container *ngFor="let set of timeSet; index as i">
<time-shift-input *ngIf="enabled"
[ngClass]="{
'mini-times' : miniTimes,
'field field-last': !miniTimes,
'field-central': !canAddSet,
'field-central--long': (canAddSet || canDeleteSet) && !miniTimes }"
[startHour]="set.startHour"
[endHour]="set.endHour"
[endsNextDay]="set.endsNextDay"
[canAddSet]="canAddSet()"
[canDeleteSet]="canDeleteSet(i)"
[required]="true"
(onAddSet)="onAddSet(i)"
(onDeleteSet)="onDeleteSet(i)"
(onChange)="onShiftTimes($event, i)"></time-shift-input>
</ng-container>
Below is the code that updates the timeSet
array after triggering the onChange
event:
public onShiftTimes( set: TimeSchedule | Array<TimeSchedule>, ind?: number ): void {
if ( ind !== undefined ) {
this.timeSet[ind] = <TimeSchedule>set;
} else {
this.timeSet = <Array<TimeSchedule>>set;
}
this.timeChanged.emit({
data: this.timeSet,
di: this.dayIndex
});
}
Every time the onShiftTimes
method is called, the child component <time-shift-input>
gets re-rendered, even if the length of the array remains the same.
This negatively impacts user experience by disrupting focus and other elements. Initially, it was assumed that pushing or updating an index of an existing array would not change the object reference, preventing the ngFor
loop from being triggered. However, surprisingly, ngOnInit
in <time-shift-input>
is still being called every time after onShiftTimes
...
Do you have any suggestions to avoid this unwanted re-rendering?