@@ -170,10 +170,20 @@ Do _NOT_ bind the `name` field.
170170When using ` [formField] ` , you MUST NOT set the following attributes in the template (either static or bound):
171171
172172- ` min ` , ` max ` (Use validators in the schema instead)
173- - ` value ` , ` [value] ` , ` [attr.value] ` (Already handled by ` [formField] ` )
173+ - ` value ` , ` [value] ` , ` [attr.value] ` on ** text/number/date inputs ** (Already handled by ` [formField] ` )
174174- ` [attr.min] ` , ` [attr.max] `
175175- ` [disabled] ` , ` [readonly] ` (Already handled by ` [formField] ` )
176176
177+ ** Exception** : Static ` value ` on ` <input type="radio"> ` and ` <input type="checkbox"> ` is ** allowed and required** — it identifies which option the input represents, not the bound field value.
178+
179+ ``` html
180+ <!-- CORRECT: value on radio specifies which option this button represents -->
181+ <input type =" radio" value =" economy" [formField] =" bookingForm.package.tier" />
182+
183+ <!-- WRONG: value binding on a regular input -->
184+ <input [value] =" someVar" [formField] =" form.name" />
185+ ```
186+
177187Do NOT do this: ` <input min="1" [formField]> ` or ` <input [value]="val" [formField]> ` .
178188
179189``` html
@@ -506,32 +516,32 @@ form(
506516
507517## Common Pitfalls (DO NOT DO THESE)
508518
509- | Error Scenario | WRONG (Common Mistake) | RIGHT (Correct Way) |
510- | :--------------------- | :-------------------------------------------- | :---------------------------------------------------------- |
511- | ** Accessing Flags** | ` form.field.valid() ` | ` form.field().valid() ` |
512- | ** Accessing value** | ` form.field.value() ` | ` form.field().value() ` |
513- | ** Setting value** | ` form.field.set(x) ` | Update model signal: ` this.model.update(...) ` |
514- | ** Form root flags** | ` form.invalid() ` | ` form().invalid() ` |
515- | ** Double-calling** | ` form.field()() ` | ` form.field().value() ` |
516- | ** Rules Context** | ` ({ touched }) => touched() ` | ` ({ state }) => state.touched() ` |
517- | ** Calling Paths** | ` applyWhen(p.foo, () => p.foo() === 'x') ` | ` applyWhen(p.foo, ({ valueOf }) => valueOf(p.foo) === 'x') ` |
518- | ** applyWhen args** | ` applyWhen(condition, () => {...}) ` | ` applyWhen(path, condition, schemaFn) ` - needs 3 args |
519- | ** Array length** | ` form.items().length ` | ` form.items.length ` (structural) |
520- | ** Multi-select array** | ` <select [formField]="form.tags"> ` (string[ ] ) | Use checkboxes for array fields |
521- | ** readonly attribute** | ` <input readonly [formField]> ` | Use ` readonly() ` rule in schema |
522- | ** min/max attributes** | ` <input min="1" max="10"> ` | Use ` min() ` and ` max() ` rules in schema |
523- | ** value binding** | ` <input [value]="val"> ` | Do NOT use ` [value] ` with ` [formField] ` |
524- | ** when option** | ` pattern(p.x, /.../, {when: ...}) ` | ` when ` only works with ` required() ` |
525- | ** Submit callback** | ` submit(form, () => { ... }) ` | ` submit(form, async () => { ... }) ` |
526- | ** Async params** | ` params: s.field ` | ` params: ({ value }) => value() ` |
527- | ** Async onError** | Omitting ` onError ` | ` onError ` is REQUIRED in ` validateAsync ` |
528- | ** resource() API** | ` request: signal ` | ` params: signal ` |
529- | ** applyEach args** | ` applyEach(s.items, (item, index) => ...) ` | ` applyEach(s.items, (item) => ...) ` |
530- | ** Nested @for ** | ` $parent.$index ` | Use ` let outerIndex = $index ` |
531- | ** FormState import** | ` import { FormState } ` | ` FormState ` does not exist, use ` FieldState ` |
532- | ** Null in model** | ` signal({ name: null }) ` | ` signal({ name: '' }) ` or ` signal({ age: 0 }) ` |
533- | ** Validate syntax** | ` validate(s.field, { value } => ...) ` | ` validate(s.field, ({ value }) => ...) ` |
534- | ** Checkbox Array** | ` [formField]="form.tags" ` (string[ ] ) | Checkboxes ONLY bind to ` boolean ` |
519+ | Error Scenario | WRONG (Common Mistake) | RIGHT (Correct Way) |
520+ | :--------------------- | :-------------------------------------------- | :------------------------------------------------------------------------------- |
521+ | ** Accessing Flags** | ` form.field.valid() ` | ` form.field().valid() ` |
522+ | ** Accessing value** | ` form.field.value() ` | ` form.field().value() ` |
523+ | ** Setting value** | ` form.field.set(x) ` | Update model signal: ` this.model.update(...) ` |
524+ | ** Form root flags** | ` form.invalid() ` | ` form().invalid() ` |
525+ | ** Double-calling** | ` form.field()() ` | ` form.field().value() ` |
526+ | ** Rules Context** | ` ({ touched }) => touched() ` | ` ({ state }) => state.touched() ` |
527+ | ** Calling Paths** | ` applyWhen(p.foo, () => p.foo() === 'x') ` | ` applyWhen(p.foo, ({ valueOf }) => valueOf(p.foo) === 'x') ` |
528+ | ** applyWhen args** | ` applyWhen(condition, () => {...}) ` | ` applyWhen(path, condition, schemaFn) ` - needs 3 args |
529+ | ** Array length** | ` form.items().length ` | ` form.items.length ` (structural) |
530+ | ** Multi-select array** | ` <select [formField]="form.tags"> ` (string[ ] ) | Use checkboxes for array fields |
531+ | ** readonly attribute** | ` <input readonly [formField]> ` | Use ` readonly() ` rule in schema |
532+ | ** min/max attributes** | ` <input min="1" max="10"> ` | Use ` min() ` and ` max() ` rules in schema |
533+ | ** value binding** | ` <input [value]="val"> ` | Do NOT use ` [value] ` with ` [formField] ` (static ` value ` on radio/checkbox is OK) |
534+ | ** when option** | ` pattern(p.x, /.../, {when: ...}) ` | ` when ` only works with ` required() ` |
535+ | ** Submit callback** | ` submit(form, () => { ... }) ` | ` submit(form, async () => { ... }) ` |
536+ | ** Async params** | ` params: s.field ` | ` params: ({ value }) => value() ` |
537+ | ** Async onError** | Omitting ` onError ` | ` onError ` is REQUIRED in ` validateAsync ` |
538+ | ** resource() API** | ` request: signal ` | ` params: signal ` |
539+ | ** applyEach args** | ` applyEach(s.items, (item, index) => ...) ` | ` applyEach(s.items, (item) => ...) ` |
540+ | ** Nested @for ** | ` $parent.$index ` | Use ` let outerIndex = $index ` |
541+ | ** FormState import** | ` import { FormState } ` | ` FormState ` does not exist, use ` FieldState ` |
542+ | ** Null in model** | ` signal({ name: null }) ` | ` signal({ name: '' }) ` or ` signal({ age: 0 }) ` |
543+ | ** Validate syntax** | ` validate(s.field, { value } => ...) ` | ` validate(s.field, ({ value }) => ...) ` |
544+ | ** Checkbox Array** | ` [formField]="form.tags" ` (string[ ] ) | Checkboxes ONLY bind to ` boolean ` |
535545
536546## Big Form Example
537547
0 commit comments