錯誤百科

子元件中的 NgModel 無法連上父層表單

當 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 輸入元素的元件為同一個——如果不同,請套用上述其中一種選項。