Angular Basics
1. Liftcycle Hooks
The following image shows the lifecycle hooks of Angular component. The directives in red block are all lifecycle hooks.
constructor()
: This will always be called at first.ngOnChanges(changes: SimpleChanges): void {}
: Check changes of the component.- Called before any other lifecycle hook. Use it to inject dependencies, but avoid any serious work here.
- Called when intput properties of component changes.
changes
is a dict type object (key: property name, value: SimpleChange). - Add
implements OnChanges
to the class.
ngOnInit()
: Initialize the component. In this func we can safely use properties and methods of component.ngAfterContentInit(): void {}
: Initialize the content of component.- Called after
ngOnInit
when the component’s or directive’s content has been initialized. - Add
implements AfterContentInit
to the class. - By default, our component doesn’t support nesting. That is in the below example the
Hello
will not be displayed in the view. To display it, we add an<ng-content>
tag in theScrollableTabComponent
to let the component have a content.<app-scrollable-tab [menus]="menus" [backgroundColor]="scrollableTabBgColor" (tabSelected)="handleTabSelected($event)"> <div>Hello</div> </app-scrollable-tab>
- Called after
ngAfterContentChecked(): void {}
: Check invalid data in the content of component. Called after every check of the component’s or directive’s content.ngAfterViewInit()
: Initialize the view of the component.- View includes the component and all its sub-components.
- Called after ngAfterContentInit when the component’s view has been initialized. Applies to components only.
ngAfterViewChecked(): void {}
: Check invalid data in the view. Called after every check of the component’s view. Applies to components only.ngOnCheck(): void {}
: Check invalid data of component.- Called every time that the input properties of a component or a directive are checked.
- Use it to extend change detection by performing a custom check.
ngOnDestroy(): void {}
: Called once, before the instance is destroyed. How to trigger this directive. We can use*ngIf
, if it is falsy the component will be destroyed. For example, This is used when we want to do some clearance, e.g. when setting interval.<app-scrollable-tab [menus]="menus" [backgroundColor]="scrollableTabBgColor" (tabSelected)="handleTabSelected($event)" *ngIf="scrollableTabBgColor==='red'">
2. Template reference variables
We can use #refName
to name the reference of template element. For example,
<div #helloDiv>Hello</div>
Since the scope of the refName
is global, so it should be unique. Then we can use this refName
as the reference of template element. In the following example, the @ViewChild
is a selector, used to find the DOM element or component. ElementRef
is a wrapper class of DOM element. Since DOM element is not an Angular class, so a wrapper class is needed to conveniently use and identify different types of DOM elements.
export class AppComponent {
@ViewChild('helloDiv') helloDivRef: ElementRef;
}
3. Template reference variables II
Previously, we use an ref name
in @ViewChild()
to refer to an Element. If we want to refer to an Angular component
, we can also use type name
. For example,
<app-image-slider [sliders]="imageSliders"></app-image-slider>
@ViewChild('ImageSliderComponent') imageSlider: ImageSliderComponent;
If we want to refer to multiple elements, we can use @ViewChildren(refName or typeName)
. Then declaration type should be QueryList<?>
.For example,
<img #img *ngFor="let slider of sliders" [src]="slider.imgUrl" [alt]="slider.caption">
@ViewChildren('img') imgs: QueryList<ElementRef>;
Then we can change style of DOM elements. Changing properties of DOM elements is always not recommended in Angular, since this may cause Injection. Instead we can use Renderer2
module. For example,
@import { Renderer2 } from '@angular/core';
// some codes
constructor (private rd2: Renderer2) {}
@ViewChildren('img') imgs: QueryList<ElementRef>;
ngAfterViewInit () {
this.imgs.forEach(item => {
this.rd2.setStyle(item.nativeElement, 'height', '100px')
});
}
Summary:
@ViewChild()
can be used to ref the view elements. These elements can be Angular component or DOM elements.- In
AfterViewInit
, we can safely use elements referred by@ViewChild()
. - It’s better to use
Renderer2
to operate DOM elements.
4. Carousel
We code setInterval()
method, letting each img scrollLeft
a specific length every 2 seconds. We did this in ngAfterViewInit()
.
@Input() intervalBySeconds = 2;
len = 0; selectedIndex = 0; intervalId;
ngAfterViewInit(): void {
this.len = this.sliders.length;
this.intervalId =
setInterval( () => {
this.rd2.setProperty (
this.imgSlider.nativeElement,
'scrollLeft',
(this.getIndex(++this.selectedIndex) *
this.imgSlider.nativeElement.scrollWidth /
this.len)
);
}, this.intervalBySeconds * 2000);
}
getIndex(idx: number): number{
//const len = this.sliders.length;
return idx >= 0 ? idx % this.len : this.len - (Math.abs(idx) % this.len);
}
handleScroll(ev) {
//const len = this.sliders.length;
const ratio = ev.target.scrollLeft / (ev.target.scrollWidth / this.len);
this.selectedIndex = Math.round(ratio);
}
Do the clearance work in ngOnDestroy()
.
ngOnDestroy(): void {
clearInterval(this.intervalId);
}
next