@ContentChild 裝飾器
基本概念
當元件的模板使用 <ng-content>
進行內容投影時,被投影的內容實際上不是該元件模板的一部分。這時 @ViewChild
/ @ViewChildren
無法選擇這些投影內容,需要使用 @ContentChild
/ @ContentChildren
來訪問投影內容中的元素。
@ViewChild 與 @ContentChild 的區別
@ViewChild
:選擇元件自身模板中的元素@ContentChild
:選擇投影到元件中的內容元素
基本語法
@ContentChild(selector, { static?: boolean }) name: ElementRef<Type>;
selector:可以是 component、directive、template reference variable(字串)或 TemplateRef
static:可選參數,決定查詢結果什麼時候解析
static: true
- 在ngOnInit
中可用static: false
(默認值)- 在ngAfterContentInit
中可用
name:元件類中用來存儲查詢結果的屬性名
Type:選擇器獲取的元素類型
使用範例
假設有以下元件結構:
control.component.html(父元件)
<label>{{ label }}</label>
<ng-content select="input, textarea" />
new-ticket.component.html(使用父元件的元件)
<form (ngSubmit)="onSubmit(titleInput.value, textInput.value)" #form>
<app-control label="Title">
<input name="title" id="title" #titleInput #input/>
</app-control>
<app-control label="Request">
<textarea name="request" id="request" rows="3" #textInput #input></textarea>
</app-control>
<p>
<button appButton>
Submit
<span ngProjectAs="icon">⌲</span>
</button>
</p>
</form>
control.component.ts(父元件)
@ContentChild('input') private control?: ElementRef<HTMLInputElement | HTMLTextAreaElement>;
生命週期注意事項
@ContentChild
引用的元素在 ngAfterContentInit
生命週期鉤子中可用:
typescriptCopyngAfterContentInit() {
// 這裡可以安全地訪問 ContentChild 元素
if (this.control) {
console.log(this.control.nativeElement);
}
}
Angular 17+ 函數式寫法
在 Angular 17+ 中,也提供了函數式寫法:
private control = contentChild<ElementRef<HTMLInputElement | HTMLTextAreaElement>>('input');
重要注意事項:
一個模板中可以有多個相同的模板變量,也可以對一個元素添加多個模板變量
使用
@ContentChild
而非@ContentChildren
是因為這個例子中每個 app-control 元件實例只獲取第一個 input 或 textarea<ng-content>
的select
屬性可以使用 CSS 選擇器指定要投影的內容ngProjectAs
屬性可以指定元素如何被<ng-content>
的選擇器匹配(如範例中的<span ngProjectAs="icon">⌲</span>
)
Last updated