當 ngModel(或任何範本驅動的表單控制項)被放在子元件裡,而父元件承載著表單指令(NgForm 或 FormGroupDirective),但該控制項無法向該表單註冊時,就會發出這個警告。
根本原因是 NgModel 會以 @Host() 注入 ControlContainer,這會阻止注入器跨越元件邊界。父元件範本中的表單指令,對子元件範本裡的 NgModel 來說是看不見的。
結果就是,子元件的控制項會默默地以獨立方式運作——它們不會參與父層表單的值、有效性或提交狀態。
修復這個警告
選項 1:用 viewProviders 橋接 ControlContainer
在子元件中加入 viewProviders,讓它把父層表單重新匯出到自己的檢視中。請使用警告訊息所指名的同一個類別——範本驅動表單(<form>)使用 NgForm,反應式表單([formGroup])使用 FormGroupDirective:
// Parent uses a template-driven form: <form> ... <app-child> </form>
import {ControlContainer, NgForm} from '@angular/forms';
import {Component} from '@angular/core';
@Component({
selector: 'app-child',
template: `<input name="email" [(ngModel)]="email" />`,
viewProviders: [{provide: ControlContainer, useExisting: NgForm}],
})
export class Child {
email = '';
}
// Parent uses a reactive form: <div [formGroup]="myGroup"> ... <app-child> </div>
import {ControlContainer, FormGroupDirective} from '@angular/forms';
import {Component} from '@angular/core';
@Component({
selector: 'app-child',
template: `<input name="email" [(ngModel)]="email" />`,
viewProviders: [{provide: ControlContainer, useExisting: FormGroupDirective}],
})
export class Child {
email = '';
}
這樣一來,父層表單就能像平常一樣看到子元件的控制項,並對它們進行驗證。
選項 2:將控制項標記為獨立
如果子元件的控制項本來就應該獨立於父層表單,請明確地退出:
<input name="email" [(ngModel)]="email" [ngModelOptions]="{standalone: true}" />
如何除錯
警告訊息包含錯誤碼 NG01354。利用呼叫堆疊找出是哪個 ngModel 觸發了它。檢查擁有 <form> 標籤的元件,是否與擁有 ngModel 輸入元素的元件為同一個——如果不同,請套用上述其中一種選項。