範本在元素上使用 [formField] 指令時,繫結或以靜態屬性設定的某個屬性,已經由訊號表單所控制。
欄位狀態是 min、max、required、disabled 與 readonly 這類屬性的單一事實來源。在範本中指定它們,會與欄位的結構定義邏輯衝突。
錯誤訊息會指出該繫結,內容為 "Binding to '[min]' is not allowed..." 或 "Setting the 'required' attribute is not allowed..."。
import {Component, signal} from '@angular/core';
import {form, FormField} from '@angular/forms/signals';
@Component({
selector: 'app-root',
imports: [FormField],
template: `
<!-- NG8022: [min] and [max] are not allowed with [formField]. -->
<input type="number" [formField]="f.age" [min]="18" [max]="99" />
<!-- NG8022: the required attribute is not allowed with [formField]. -->
<input type="text" [formField]="f.name" required />
`,
})
export class App {
f = form(signal({age: 20, name: ''}));
}
當範本在自訂表單控制項上繫結了欄位所管理的輸入時(例如在宣告了 max 輸入的控制項上使用 [max]),同樣會發生這個錯誤。
不能與 [formField] 併用的屬性包括:
- 值:
value、checked(由底層的模型訊號直接管理) - 驗證規則:
required、min、max、minLength、maxLength、pattern(以及原生 HTML 的minlength與maxlength) - 互動狀態:
disabled、readonly、hidden - 欄位狀態與中繼資料:
name、dirty、touched、invalid、errors、pending、disabledReasons(在自訂控制項上,FormField會自動把這些狀態傳給控制項,所以手動繫結它們會與框架的自動接線衝突)
原生元素上有少數例外:
min與max可用於date、time、month、week與datetime-local類型的<input>元素。在這些類型上,限制是像2026-01-01這樣的日期或時間字串,數值型的min()與max()規則無法表達。- 當
type是動態繫結時,min與max也可用,因為編譯器無法知道 input 的類型。 value可用於<input type="radio">,因為在那裡它用來識別選項。由欄位值決定哪個 radio 按鈕被選取。
除錯方式
從範本中移除該繫結,再依其類別處理該屬性:
- 值(
value、checked):[formField]會自動把元素與底層的模型訊號繫結並雙向同步。若要初始化或變更值,請更新傳給form()的模型訊號。 - 驗證規則(
required、min、max、maxLength等): 在form()的結構定義函式中使用對應的驗證規則來宣告。 - 互動狀態(
disabled、readonly、hidden): 使用結構定義規則disabled()、readonly()與hidden(),它們也接受選用的when條件,因此規則可以取決於其他欄位。請見表單邏輯。 - 欄位狀態與中繼資料(
dirty、touched、errors等): 不需要替代寫法。[formField]會從欄位狀態套用它們,你也可以從欄位讀取,例如f.age().dirty()。
上述範例改寫後如下:
import {Component, signal} from '@angular/core';
import {disabled, form, FormField, max, maxLength, min, required} from '@angular/forms/signals';
@Component({
selector: 'app-root',
imports: [FormField],
template: `
<input type="number" [formField]="f.age" />
<input type="text" [formField]="f.name" />
`,
})
export class App {
f = form(signal({age: 20, name: ''}), (p) => {
min(p.age, 18);
max(p.age, 99);
required(p.name);
maxLength(p.name, 20);
disabled(p.name, {when: ({valueOf}) => valueOf(p.age) < 18});
});
}