Hi friends Welcome back to the brand new series on Angular
- Zero to Hero. A perfect Angular guide for beginners. In my last video, I have explained about Template
Reference Variable and @ViewChild. In this video, I am going to explain about
Life Cycle Hooks in Angular. All components and directives in Angular have
a lifecycle as Angular creates, updates, and destroys them. We can implement the lifecycle hook interfaces
and use the respective method to tap into any lifecycle moments. Components have more lifecycle hooks than
directives. These are the common lifecycle hooks available
in both components and directives and these are the lifecycle hooks available only in
components to be more specific we can say in children components. As a side note, constructor is not a life
cycle hook. It is a typescript feature. I will be explaining more about constructor,
it's use and the difference between ngOnInit and constructor in a separate video. Now let me explain all the component hooks
using a program. I have created an application and started
the server. I have also created a parent and a child component. In app component, I have added the parent
component and in parent component I have added the child component. And so we can see this. Now, let's start with ngOnInit. ngOnOnit will be invoked when the component
has initialized. This hook will be called only once after the
first ngOnChanges. We can implement the OnInit interface to use
this hook. Mostly, we use ngOnInit for doing initializations. When we create a component using Angular CLI,
we can see the ngOnInit hook has been implemented already. So, let me add few console.log in both parent
and child components. Now we can see, the parent component constructor
is called first and then the child component constructor is called. And then the parent component ngOnInit is
called and then the child component oninit method is called. Now, let me add a button in parent component
and display the child component when the button is clicked. So now, we can see only the parent constructor
is called and then the parent oninit is called. Child component hooks are not called because
child component is not yet initialized. Now, when I click the button, we can see the
child constructor is called and child oninit method is also called. So, we can understand once the component is
loaded into the dom, that component's constructor and the oninit method will be called. Now, let's move to ngOnDestroy. OnDestroy will be called once just before
the component is removed from the DOM, in other words when the component is destroyed
from the DOM. Let me introduce ngOnDestroy by implementing
the OnDestroy interface in child component. When I click the button, we can see constructor
is called once and then OnInit is called. If I click again, OnDestroy is called and
so component is removed. If I click again, component is constructed
again so constructor is called again and then oninit is called. Clicking again will destroy it. We can understand, OnDestroy will be called
once when the component is removed from the DOM. So, if we need any cleaning activities we
can do it in OnDestroy. Let me explain, why we need to use OnDestroy. Let me add a counter and in oninit let me
increment that every second and printing that in the console. So, once I initialize the component we can
see the counter getting incremented. But, when I destroy the component, we can
see the component is destroyed but the interval we created is still running, so if I toggle
the button again we can see two intervals are running and even after destroying they
are still running. So, this is a memory leak. We should avoid these type of memory leak. So, we can use onDestroy to clear these intervals,
we can unsubscribe if we subscribe any observables, etc. So, in child component let me get the interval
and clear that in onDestroy hook. So, when I click once, we can see the counter
has started and when I destroy the component, we can see the counter is also cleared. If I click again a new counter is starting
and now it is stopped. So, we have fixed the memory leak. This is the use of ngOnDestroy. Now, let's see about ngOnChanges. OnChanges will be called once before OnInit
and will be called whenever the data-bound input properties changes. When I say data-bound input, it is not the
normal input in the same component. It should be something coming outside of that
component through @Input. Let me explain. I have created an input and used two-way binding. I am also showing the value there. Let me import forms module. And, let me also comment these codes and change
this flag to initialize the child component when page loads. And, let me also implement OnChanges interface
and define ngOnChanges method and put some console logs in both the components. Now, we can see ngOnchanges is not called
before OnInit. Even, if I change this input value, we can
see the value is getting changed but still the ngOnchanges is not called. Now, let me move this input to parent component
and pass this to child component through @Input. Now, when we load the page, we can see parent
constructor is called and then parent oninit is called after that child constructor is
called and before child oninit we can see child onchanges is called once. When I change this input value in parent,
the onchanges in child is called for every keystroke. so, it is not a good practice to do any expensive
operations like API call inside onChanges. Also, ngOnChanges accepts a SimpleChanges
object and using that we can make use of previous and current values. Let me show that. So, here initially the currentValue is empty
string, previous value is undefined and firstChange is true. if I type a, we can see the currentValue is
"a" now. PreviousValue is empty string and first change
is false. Again, if I type b, we can see the current
value is "ab", previous value is "a" and first change is false. So, using this we can do something, if any
particular input value changes.This is about ngOnchanges. Now, lets look into ngDoCheck. docheck will be invoked when the change detector
of the given component is invoked. It is called immediately after ngOnChanges()
on every change detection run, and immediately after ngOnInit() on the first run. Let me implement docheck in both the components. Now, when we load, we can see parent docheck
is called just after parent oninit and child do check is called just after child oninit. And, in development mode change detection
run twice and so we can see Docheck is called one more time in each component. And, when I click the button in parent, we
can see the parent do check is called. Also, when I type, docheck is called again. even when I click outside after typing, it
is called. Similarly, when I type something in parent,
it triggers the onchanges in child because it is an inbound property. But, we can also see the child docheck is
called after child onchanges to detect changes. So, we should avoid triggering any expensive
operations inside ngDoCheck. Also, we should avoid using ngOnChanges and
ngDoCheck in the same component. I have used now just for explaning these concepts. Sometimes, the change detection triggers another
change and it became an infinite loop. So, we should be careful about that. These are the general lifecycle hooks in both
components and directives. Now let's see about component only life cycle
hooks. First, lets see ngAfterContentInit. ngAfterContentInit will be called only once
after the first docheck. To understand this hook, I need to explain
about content projection. Assume I wanted to send or project some content
into child from parent. I can do it like this. As it is also a tag, we can expect this to
show in child component but, it won't show. We need to inform Angular where exactly we
need to show the projected content. For that, we can use ng-content directive. So, when I add we can see the projected content
is displaying in the child component. This is content projection and this will be
very useful when we create reusable widgets. Now, lets come back to lifecycle hooks. I am implementing AfterContentInit and then
defining ngAfterContentInit method. Now, in the parent content let me add a template
reference variable. We know how to access the template reference
variable using @ViewChild and as this template reference variable is in content, we can access
it in child component using @ContentChild. Also in child component let me add some console
logs in onInit, onChanges, doCheck and AfterContentInit. If we load the page, we can see AfterContentInit
is called after Child docheck and also, we cannot access this variable till the content
is initialized. That means, in all other hooks this is coming
as undefined and only in AfterContentInit this is not undefined. Hope you understands AfterContentInit hook. Let's also see AfterContentChecked hook. ngAfterContentChecked will be called after
ngAfterContentInit() and every subsequent ngDoCheck(). Let me quickly implement AfterContentChecked
interface and use that method with a console.log. Now, we can see it is called after AfterContentInit. And, if I type something, we can see it is
called after every doCheck. Now we have ngAfterViewInit and ngAfterViewChecked. ngAfterViewInit will be called once after
the first ngAfterContentChecked and ngAfterViewChecked will be called after ngAfterViewInit and after
every subsequent ngAfterContentChecked. Let me quickly implement the interfaces, define
the methods and put some console logs. Now, we can see AfterViewInit is called once
after AfterContentChecked. And ngAfterViewChecked is called after ngAfterViewInit
and after subsequent ngAfterContentChecked. If I type something, we can see ngAfterContentChecked
is called and after that ngAfterViewChecked is also called. This is all about Life Cycle Hooks. And, if you remember When I was explaining
about template reference variable and @ViewChild I told I will explain about static option
in ViewChild which was introduced as part of Angular 9. Let's see that. Let me quickly add some console.logs to see
whether we are able to access childcontent inside all hooks. Like how we can access the parent content
only after content is initialized, we can access the child content also only after the
view is initialized. That means only AfterViewInit. This is how, Angular was working in older
versions. But, in Angular 9 a second parameter was introduced. That is static. for that we can give true
or false. Same thing applicable to ContentChild as well. So, when we add static as false. we can see there is no differnce because that
is the default option. But, when we change it to true, we can see
we can access both parent and child content in ngOnchanges and ngOnInit itself. So, this is the use of the second parameter
in ViewChild and ContentChild. I hope you understand these concepts now. I suggest you to try these hooks once for
better understanding. I have also posted this code in github repo. If you want you can take it from there. I have also provided the link in the description. Next, I am going to explain about Routing
in Angular. So, if you haven't subscribe to this channel
yet, please subscribe press bell button and stay tuned. Thank you. Bye