@Input() animal = "Tiger"
editAnimal(animal: string){
this.animal = animal
}
The editAnimal function runs when a user types a new animal into a text field and presses a button to submit. Everything works as expected, but the ngOnChanges is not running, but ngDoCheck is. Can someone explain why?
There's not a lot of context about the parent component and the flow of the data to the child component on the given example.
Difference between
ngOnChanges()andngDoCheck()However, as mentioned on the official Angular Documentation - Lifecycle hooks:
Assuming that in your example, there's a parent component that passes the
animaldata down to the child component, the data will be updated once beforengOnInit()is called. If the input data are not changing, this is the reason why you're not seeing thengOnChanges()firing again - otherwise you would see thengOnChanges()being executed.Now coming to
ngDoCheck(). Again, as stated to the official documentation:The
ngDoCheck()is called after every change detection cycle run - which makes it also a very expensive hook to implement (can have a very severe penalty on performance). This lifecycle hook is executed whenever a change has occured, no matter where the change occured on the component's tree.Example
To make it clearer, we can consider the following example. Imagine that we have an application that displays some events on the screen, and users can click on events to see more details. For the sake of our example, we have only 2 events in our list - the Google Demo Conference and Angular Demo Conference.
Top Level Component: The top level component has 2 child components, a Navigation Bar Component and an Events List Component. The Navigation Bar Component contains also a search box, where users can type in and upon hitting enter, see relevant events.
Events List Component: The Events List Component has only one child component - the
EventsListItemComponent.Imagine a rough implementation of the
EventsListItemComponentas follows (notice below that we have implemented thengDoCheck()andngOnChanges()lifecycle hooks):The Navigation Bar Component looks like the below:
When the component initially loads, the following will be logged in the console:
Consider now the situation where a user just types into the navigation bar component's search box. This will trigger the
ngDoCheck()of theEventsListItemComponentto be re-executed:Depending on the number of letters typed, it would look something like the below:
A visual representation of what was described above:
What happened?
Notice on the
NavigationBarComponentthe bi-directional binding of thesearchTermproperty between the template and the component directive, i.e.,[(ngModel)]="searchTerm". So, every time we type a letter into the searchboxe's<input>property, the relevant binding is updating.Angular is detecting the changes on the Data Model of the
NavigationBarComponentwhich triggers a traversal to the hierarchical tree-component structure.At runtime, Angular creates a separate change detector class for every component in the tree, which then eventually forms a hierarchy of change detectors similar to the hierarchy tree of components.
Whenever change detection is triggered, Angular walks down this tree of change detectors to determine if any of them have reported changes.
This is when the
ngDoCheck()is called in theEventsListItemComponent- in order for changes that Angular can't catch by it's own to be detected. I suppose that something similar happens in your application as well.We could go on and talk about detection strategies and more about Angular, however, this could make the post even more bigger.
Sources and further reading
Some good readings and sources that have been used for this post: