- vừa được xem lúc

Angular: Làm việc với @ViewChild

0 0 88

Người đăng: HoangManh

Theo Viblo Asia

Angular @ViewChild decorator là 1 trong những decorator đầu tiên mà chúng ta sẽ học khi tìm hiểu về Angular. Nó thực sự quan trọng, hữu ích và quen thuộc trong Angular.

Trong bài viết này, chúng ta sẽ cùng tìm hiểu để thấy decorator này thực sự hữu ích như nào qua các mục dưới đây.

Nội dung chính:

Chúng ta sẽ đi qua các nội dung sau đây:

  1. Khi nào chúng ta cần đến @ViewChild decorator?
  2. Mối quan hệ với AfterViewInit Lifecycle Hook
  3. Scope của @ViewChild khi truy vấn template
  4. Sử dụng @ViewChild để truy vấn tới DOM element
  5. Sử dụng @ViewChild để truy vấn tới component
  6. @ViewChild với thuộc tính metadata
  7. Sử dụng @ViewChild để truy vấn tới directive
  8. Tổng kết

Khi nào chúng ta cần đến @ViewChild decorator?

Bạn muốn truy cập vào các child component, directive hay DOM element từ parent component. Việc này thật dễ dàng khi đã có ViewChild decorator.
ViewChild trả về phần tử đầu tiền mà chúng ta muốn truy vấn.
Trong trường hợp chúng ta muốn truy vấn tới nhiều phần từ con, chúng ta có thể dùng ViewChildren thay thế.

Mối quan hệ với AfterViewInit Lifecycle Hook

Nếu chúng ta muốn component con mà chúng ta truy vấn tới thực sự được khởi tạo thì chúng ta nên thực thi trong AfterViewInit lifecycle hook
Có thể sử dụng ngOnInit() thay thế ngAfterViewInit() hay không?
Tuỳ từng tình huống mà ta ngOnInit có thể thay thế được ngAfterViewInit khi dùng ViewChild được hay không. Nếu template được truy vấn thực sự đã sinh ra trong ngOnInit, thì chúng ta có thể dùng ngOnInit nhưng để chắc chắn và không quan tâm thời điểm template được sinh ra thì chúng ta không nên dùng ngOnInit.

Từ Angular 8+, Angular giới thiệu 1 Metadata Properties: static

static - True to resolve query results before change detection runs.
When static is not provided, uses query results to determine the timing of query resolution. If any query results are inside a nested view (such as *ngIf), the query is resolved after change detection runs. Otherwise, it is resolved before change detection runs.

-> Hiểu đơn giản thì static sẽ giúp dev kiểm soát được việc truy cập vào đối tượng được View là ở ngOnInit hay ngAfterViewInit. Static nhận vào giá trị boolean. Mặc định sẽ là false, khi đó ta không thể truy cập ở ngOnInit mà ở ngAfterViewInit

Scope của @ViewChild khi truy vấn template

Với @ViewChild, chúng ta có thể truy vấn vào trong component, directive hay DOM HTML nhưng nó thực sự truy vấn được đến độ sâu nào của cây component thì ta cần làm 1 phép thử sau đây:

@Component({ selector: 'color-sample', template: ` <div class="color-sample mat-elevation-z3" [style.background-color]="color"> <mat-icon>palette</mat-icon> </div> `
})
export class ColorSampleComponent { @Input() color;
}

Chúng ta có component ColorSampleComponent mà phần template có sử dụng MatIcon component.

<h2>Choose Brand Colors:</h2> <color-sample [color]="primary" #primaryColorSample>
</color-sample> <mat-input-container> <mat-label>Primary Color</mat-label> <input matInput #primaryInput [(colorPicker)]="primary" [(ngModel)]="primary"/>
</mat-input-container>
Component({ selector: 'app-root', templateUrl: './app.component.html'
})
export class AppComponent implements AfterViewInit { @ViewChild(MatIcon) matIcon: MatIcon; ngAfterViewInit() { console.log('Values on ngAfterViewInit():'); console.log("matIcon:", this.matIcon); }
}

Kết quả nếu ta chạy thử đoạn code này sẽ là: Đây là tình huống mà ta gọi ViewChild để xem 1 component nằm trong component con của AppComponent, và kết quả chúng ta thấy là ViewChild không thể xem được component cháu của mình.

Vì vậy có thể đưa ra kết luần là:
@ViewChild decorator không thể nhìn qua 1 component bị bao đóng. Điều này có nghĩa là ViewChild chỉ có thể xem được thành phần nằm bên trong template của chính nó

Sử dụng @ViewChild để truy vấn tới DOM element

Chúng ta có thể truy cập tới native DOM element thông qua biến tham chiếu template
Chúng ta biến tham chiếu template demoInput với tình huống sau:

<input #demoInput placeholder="hom nay la thu may">

Chúng ta có thể sử dụng ViewChild để truy cập tới input trên như sau:

import { Component, ViewChild, AfterViewInit, ElementRef } from '@angular/core'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css']
})
export class AppComponent implements AfterViewInit { @ViewChild('demoInput') demoInput: ElementRef; ngAfterViewInit() { this.demoInput.nativeElement.value = "Sunday!"; }
} 

Giá trị của Input sẽ được set thành Sunday! sau khi ngAfterViewInit thực thi.

Sử dụng @ViewChild để truy vấn tới DOM element của component

Không khó để chúng ta có thể truy cập tới component con và gọi method hoặc truy cập vào các biến có sẵn trong component con.
Chúng ta có hàm whoAmI như sau:

whoAmI() { return 'I am a grown-up sunner!';
}

Chúng ta có thể gọi đến method đó từ component cha khi sử dụng ViewChild như sau:

import { Component, ViewChild, AfterViewInit } from '@angular/core'; import { ChildComponent } from './child.component'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css']
})
export class AppComponent implements AfterViewInit { @ViewChild(ChildComponent) child: ChildComponent; ngAfterViewInit() { console.log(this.child.whoAmI()); // I am a grown-up sunner! }
}

@ViewChild với thuộc tính metadata:

@Component({ selector: 'app-root', templateUrl: './app.component.html'
})
export class AppComponent implements AfterViewInit { .... @ViewChild('primaryColorSample') sample: ColorSampleComponent; ngAfterViewInit() { console.log('Values on ngAfterViewInit():'); console.log("sample:", this.sample); } ....
}

Kết quả khi thực thi sẽ như sau:

Còn khi chúng ta sử dùng thuộc tính trong ViewChild

@Component({ selector: 'app-root', templateUrl: './app.component.html'
})
export class AppComponent implements AfterViewInit { @ViewChild('primaryColorSample', {read: ElementRef}) sample: ElementRef; ngAfterViewInit() { console.log('Values on ngAfterViewInit():'); console.log("sample:", this.sample.nativeElement); }
}

Kết quả khi thực thi sẽ như sau: Khi thêm option {read: ElementRef} thì chúng ta đã xem component về mặt template với cấu trúc DOM chứ không còn nhìn vào các thành phần bên trong component của nó chứa các method hay thuộc tính nào nữa.

Sử dụng @ViewChild truy vấn Directives

Chúng ta có directive:

import { Directive, ElementRef, Renderer2 } from '@angular/core'; @Directive({ selector: '[appBeautifyName]' })
export class BeautifyNameDirective { name = 'htm'; constructor(elem: ElementRef, renderer: Renderer2) { let name = renderer.createText('htm '); renderer.appendChild(elem.nativeElement, name); }
}

Chúng ta có thể sử dụng ViewChild để truy vấn đến directive bằng cách như sau:

import { Component, ViewChild, AfterViewInit } from '@angular/core'; import { BeautifyNameDirective } from './beautifyName.directive' @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css']
})
export class AppComponent implements AfterViewInit { nameApp: string; @ViewChild(BeautifyNameDirective) set appBeautifyName(directive: BeautifyNameDirective) { this.nameApp = directive.name; }; ngAfterViewInit() { console.log(this.nameApp); // htm }
}

Tổng kết

Vậy thôi, những gì bạn cần để hiểu về ViewChild ở trên, điều bạn cần bây giờ là đọc và thử nghiệm nó và ứng dụng nó đúng trường hợp.
Cám ơn và hẹn gặp lại 🙃


Tham khảo: angular-university-angular-viewchild

Bình luận

Bài viết tương tự

- vừa được xem lúc

Giới thiệu Typescript - Sự khác nhau giữa Typescript và Javascript

Typescript là gì. TypeScript là một ngôn ngữ giúp cung cấp quy mô lớn hơn so với JavaScript.

0 0 525

- vừa được xem lúc

Cài đặt WSL / WSL2 trên Windows 10 để code như trên Ubuntu

Sau vài ba năm mình chuyển qua code trên Ubuntu thì thật không thể phủ nhận rằng mình đã yêu em nó. Cá nhân mình sử dụng Ubuntu để code web thì thật là tuyệt vời.

0 0 397

- vừa được xem lúc

Đặt tên commit message sao cho "tình nghĩa anh em chắc chắn bền lâu"????

. Lời mở đầu. .

1 1 738

- vừa được xem lúc

Tìm hiểu về Resource Controller trong Laravel

Giới thiệu. Trong laravel, việc sử dụng các route post, get, group để gọi đến 1 action của Controller đã là quá quen đối với các bạn sử dụng framework này.

0 0 358

- vừa được xem lúc

Phân quyền đơn giản với package Laravel permission

Như các bạn đã biết, phân quyền trong một ứng dụng là một phần không thể thiếu trong việc phát triển phần mềm, dù đó là ứng dụng web hay là mobile. Vậy nên, hôm nay mình sẽ giới thiệu một package có thể giúp các bạn phân quyền nhanh và đơn giản trong một website được viết bằng PHP với framework là L

0 0 450

- vừa được xem lúc

Bạn đã biết các tips này khi làm việc với chuỗi trong JavaScript chưa ?

Hi xin chào các bạn, tiếp tục chuỗi chủ đề về cái thằng JavaScript này, hôm nay mình sẽ giới thiệu cho các bạn một số thủ thuật hay ho khi làm việc với chuỗi trong JavaScript có thể bạn đã hoặc chưa từng dùng. Cụ thể như nào thì hãy cùng mình tìm hiểu trong bài viết này nhé (go).

0 0 433