@ViewChild và @ViewChildren

·

3 min read

@ViewChild@ViewChildren dùng để truy cập vào đối tượng DOM hoặc child component, thường dùng khi muốn thay đổi giá trị, css class của element, thực hiện method của element ...
1. @ViewChild
Khi muốn truy cập vào 1 đối tượng DOM, 1 child component thì dùng viewchild

import { Component, ViewChild, ElementRef } from '@angular/core';

@Component({
  selector: 'app-parent',
  template: `
    <app-child #childComponent></app-child>
    <span #spanEl>test viewchild</span>
  `
})
export class ParentComponent {
  @ViewChild('inputRef') inputRef: ElementRef;
  @ViewChild('spanEl') spanEl: ElementRef;

  @ViewChild('childComponent', { read: ChildComponent, static: true }) childComponent!: ChildComponent;

@ViewChild(ChildComponent, { static: true }) childComponent1!: ChildComponent;

  ngAfterViewInit() {
    console.log(this.inputRef.nativeElement.value);
    console.log(this.spanEl.nativeElement.value);
    console.log(this.childComponent.helloWorld());
    console.log(this.childComponent1.helloWorld());
  }
}

@Component({
  selector: 'app-child',
  template: `
    <input #inputRef type="text" value="Hello World">
  `
})
export class ChildComponent {
    public helloWorld() {
        console.log("Hello world");
    }
}

Trên là 1 số cách để lấy @Viewchild
Chú ý 2 options:
- read: là kiểu dữ liệu của đối tượng sẽ được trả về. Nó được sử dụng để chỉ định loại của tham chiếu mà ta muốn nhận (thường là ElementRef, TemplateRef, ViewContainerRef, 1 component, 1 directive ...).
- static: là một giá trị boolean cho biết liệu bạn muốn tham chiếu đến thành phần bằng cách sử dụng tĩnh (true) hay động (false).
+ Khi static = true, đối tượng sẽ được lấy trong quá trình khởi tạo của component cha và nó sẽ không được cập nhật khi thành phần con thay đổi.
+ Khi static = false (mặc định), đối tượng sẽ được lấy khi component cha được khởi tạo và sau đó được cập nhật khi element này thay đổi.
\=> Nếu chắc chắn đối tượng mình lấy không thay đổi => set static = true, ngược lại thì để mặc định (false).

2. @ViewChildren

Dùng @ViewChild để query 1 element thì @ViewChildren để query 1 list element, @ViewChildren đi với QueryList. Dưới đây là 1 số cách dùng @ViewChildren.

import { Component, ViewChild, ElementRef, ViewChildren, QueryList } from "@angular/core";

@Component({
  selector: "app-parent",
  template: `
    <app-child #childComponent></app-child>
    <app-child #childComponent></app-child>
    <span #childEl>viewchild 1</span>
    <span #childEl>viewchild 2</span>
  `,
})
export class ParentComponent {
  @ViewChildren("spanEl") public spanEls!: QueryList<ElementRef>;

  // data type cua  childElementRef laf ElementRef
  @ViewChildren(ChildComponent, { read: ElementRef })
  public childElementRef!: QueryList<ElementRef>;

  @ViewChildren(ChildComponent)
  public childComponents!: QueryList<ChildComponent>;

  @ViewChildren('childEl', { read: ChildComponent })
  public childElComponent!: QueryList<ChildComponent>;

  ngAfterViewInit() {
    this.spanEls.forEach((span) => {
      console.log(span.nativeElement.classList);
    });

    this.childElementRef.forEach((element) => {
      console.log(element.nativeElement);
    });

    this.childComponents.forEach((child) => {
      child.helloWorld();
    });

    this.childElComponent.forEach(e => {
      e.helloWorld();
    });

  }
}

@Component({
  selector: "app-child",
  template: ` <input #inputRef type="text" value="Hello World" /> `,
})
export class ChildComponent {
  public helloWorld() {
    console.log("Hello world");
  }
}

- read: Tương tự với read của ViewChild
3. Kết luận
- Khi muốn truy cập 1 DOM element, 1 child component thì dùng @ViewChild.

- Khi muốn truy cập vào 1 list DOM elements, 1 list child components thì dùng @ViewChildren.