Angular NgOnChanges behaving weirdly

142 views Asked by At

I have a parent component sending data to a child component via Input. NgOnChanges won't work as I expect it to be. I know that it does not work well with object/array because they are sent via reference so Angular has trouble detecting changes.

So I tried the workaround of assigning it to a new object with Object.assign() to create a new reference but it does not work.

Parent TS:

public selectSchedule(index) {
this.oldWeeklyScheduleSelected = this.weeklyScheduleSelected;
if (index != this.weeklyScheduleSelected) {
  this.weeklyScheduleSelected = index;
  this.selectedActivity = undefined;
}
this.http.getDefaultWeekPlanning(this.idOrganisation, this.userId, this.weeklyScheduleCreated[index]
).subscribe((data: any) => {
  if (data === undefined || data.length === 0) {
    this.sendScheduleToChild.scheduleSlot = [];
  } else {
    this.sendScheduleToChild.scheduleSlot = data;
    this.sendScheduleToChild.existingSchedule = true;
    this.sendScheduleToChild = Object.assign({}, this.sendScheduleToChild);
    console.log(this.sendScheduleToChild.scheduleSlot);
  }
}
}

Child TS:

@Input() sendScheduleToChild: any;

ngOnChanges(changes: SimpleChanges) {
console.log(changes)
if (this.oldWeeklyScheduleSelected != this.weeklyScheduleSelected && this.oldWeeklyScheduleSelected != undefined) {
  this.daysOfWeek.forEach(e => {
    e.scheduleSlot = [];
  });
  this.scheduleOfEachDay();
} else {
  this.scheduleOfEachDay();
}

if (this.sendScheduleToChild.existingSchedule === true && this.sendScheduleToChild.scheduleSlot.length === 0) {
  this.hoursOfDayDisplay(this.editAgenda);
}
}

oldWeeklyScheduleSelected and weeklyScheduleSelected works well because they are number.

sendScheduleToChild does not on the first click. But it will on the second afterwards but my data will messed up at that point.

console.log(changes) shows the variables that are changed but in the case of sendScheduleToChild, both previous and current values are the same while it is not the case for the two others.

I do not understand why it does not detect changes at first but will after 2 clicks since the data sent is of the same type.

Any help appreciated.

P.S:

I tried to modify the reference of the object by changing the value with :

if (data === undefined || data.length === 0) {
    this.sendScheduleToChild.scheduleSlot = [];
  } else {
    this.sendScheduleToChild = {
      scheduleSlot: data,
      existingSchedule: true
    };

But it still behave unexpectidely.

2

There are 2 answers

0
makinyelure On

You can try creating a setter around the variable on the input element. In you child element, do

private _schedule: any;

@Input('sendScheduleToChild')
set sendScheduleToChild(schedule: any) {
   this._schedule = schedule;
}

In you parent component view, simply do

<childComponent [sendScheduleToChild]="{value}"></childComponent>

ngOnChanges should be able to catch the changes after this.

0
Vugar Abdullayev On

OnChanges triggers change when you change 'Reference' of input object. But currently you just change the value , you should assign sendScheduleToChild to new object. Like this:

this.sendScheduleToChild = {
 ...sendScheduleToChild,
 scheduleSlot: data;
 existingSchedule: true,
};