Project - Groupbuy App Part II

prev

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 the ScrollableTabComponent to let the component have a content.
       <app-scrollable-tab [menus]="menus" [backgroundColor]="scrollableTabBgColor" (tabSelected)="handleTabSelected($event)"> 
       	<div>Hello</div>
      </app-scrollable-tab>
  • 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.

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

   Reprint policy


《Project - Groupbuy App Part II》 by Tong Shi is licensed under a Creative Commons Attribution 4.0 International License
  TOC