Change Detection NOT working?

I am sure many of you have come crossed this situation where angular application data have been changed but still change detection might not have triggered and you are left wondering what just happened…

Have the data not changed? Has the view not rendered?

Today, I’ll brief one scenario where change detection will not trigger though the data have changed

In the below example:

I have one parent app-component, which will initialize the todo list and will add value to the todo list. This component has two child components as add-todo-items and show-todo-list as shown below.

add-todo-items will add todo items in the list and show-todo- list will show the todo-list.

After you enter a todo-item in the input and click add button you will see the item will not get added in the list.

app.component.ts

mytodolist: string[];
ngOnInit() {
this.mytodolist = [
'Recharge Cell Phone',
'Order Groceries',
'Renew Vehicle License'
];
}
addValue(todoitem){
this.mytodolist.push(todoitem);
console.log('New Updated List is ===>', this.mytodolist);
}

app.component.html

<app-add-todo-items (newValue)="addValue($event)"></app-add-todo-items><br><app-show-todo-items [TodaysTodoList]="mytodolist"></app-show-todo-items>

add-todo-items.component.ts

newTodoItem;
@Output() newValue: EventEmitter<any> = new EventEmitter();
createValue() {
this.newValue.emit(this.newTodoItem);
this.newTodoItem = '';
}

add-todo-items.component.html

<input type="text" [(ngModel)]="newTodoItem" /><button (click)="createValue()">Add Todo Item</button>

show-todo-items.component.ts

@Input() TodaysTodoList;
public lowercaseValues: string[] = [];
ngOnChanges() {
this.lowercaseValues = [];
console.log('Updated Show list here==>', this.TodaysTodoList);
this.TodaysTodoList.forEach(v => {
this.lowercaseValues.push(v.toLowerCase());
});
}

show-todo-items.component.html

<div *ngFor="let value of lowercaseValues">
{{value}}
</div>

Now you must be thinking that why new todo-item has not rendered on the UI though todo-list has updated successfully in the parent component. (Below Image)

The answer is change- detection. Yes, you are correct the list is updated successfully, but the child component (show-todo-list) has not updated with the latest values because the reference of the array of todo-list in parent component has not changed and that’s why change detection has not triggered for child component.

Solution: Change detection will only trigger if reference of object has been changed.

Below Updated code: Reference of the array has been updated

app.component.ts

addValue(todoitem){
this.mytodolist.push(todoitem);
console.log('New Updated List is ===>', this.mytodolist);
this.mytodolist = [... this.mytodolist];
}

Many of you must be thinking what will happen if we update the list inside observable? But still, we have to change the reference of an array to emit change detection.

(That I’ll leave to you to try … )