상위컴포넌트에서 하위컴포넌트의 인스턴스가 필요할때 사용한다.
@ViewChild(하위컴포넌트타입) 속성데코레이터이며 하위컴포넌트의 타입을 인자로 전달하면 템플릿에서 해당 타입의 컴포넌트 인스턴스를 찾아 반환한다.
정확히 말하면 클래스 인스턴스를 얻는다고 하는 것이 맞다.
클래스코드에서 @ViewChild를 사용하여 얻는 것은 클래스 인스턴스이고 클래스 인스턴스이기때문에 프로퍼티에 접근할 수 있는 것이다.
아래에서 보겠지만 클래스인스턴스에서 nativeElement프로퍼티를 사용하면 해당 DOM노드에 접근할 수 있다.
import {AfterViewInit, Component, Directive, ViewChild} from '@angular/core';
@Directive({selector: 'child-directive'})
class ChildDirective {
}
@Component({selector: 'someCmp', templateUrl: 'someCmp.html'})
class SomeCmp implements AfterViewInit {
@ViewChild(ChildDirective) child!: ChildDirective;
ngAfterViewInit() {
console.log(this.child);
}
}
@ViewChild(ChildDirective) child!: ChildDirective;
ChildDirective타입을 인자로 전달하고 변수를 선언한다.
뷰가초기화되는 라이프사이클 후킹함수 ngAfterViewInit에서 인스턴스가 할당되어 접근이 가능해진다.
import {Component, Directive, Input, ViewChild} from '@angular/core';
@Directive({selector: 'pane'})
export class Pane {
@Input() id!: string;
}
@Component({
selector: 'example-app',
templateUrl: 'someCmp.html'
})
export class ViewChildComp {
@ViewChild(Pane)
set pane(v: Pane) {
setTimeout(() => {
this.selectedPane = v.id;
}, 0);
}
selectedPane: string = '';
shouldShow = true;
toggle() {
this.shouldShow = !this.shouldShow;
}
}
@ViewChild(Pane)
set pane(v: Pane) {
setTimeout(() => {
this.selectedPane = v.id;
}, 0);
}
ViewChild데코레이터 Pane타입을 전달하고 pane:Pane하면 되겠지만 위 코드처럼 pane:setter함수를 사용하면 pane이 인스턴스로 할당될때 함수가 호출된다.
ViewChild를 사용하면 자식 컴포넌트의 요소노드에 접근할 수 있다.
<button #btn>!!!</button>
템플릿 요소노드에 템플릿변수를 사용한다.
@ViewChild('btn') childBtn!:any;
ngAfterViewInit(): void {
(this.childBtn.nativeElement as HTMLButtonElement).addEventListener('click',()=>{alert(2)});
}
nativeElement프로퍼티를 사용하면 DOM요소노드를 접근할 수 있다.
상위컴포넌트가 하위컴포넌트의 뷰상태변경을 감지하려면 (예로 입력필드에 포커스인, 포커스아웃) ngAfterViewChecked함수를 사용해야 한다.
@ViewChild 프로퍼티데코레이터를 사용하면 하위클래스인스턴스를 얻고 프로퍼티에 접근이 가능하다.