mirror of
https://github.com/angular/angular.git
synced 2026-09-14 13:54:52 +08:00
docs(forms): document what required() considers empty
The `required()` validator treats `null`, `undefined`, `''`, `false` and `NaN` as empty, but the API
docs never defined "empty" at all and the validation guide listed only `null` and `''`.
(cherry picked from commit 467b37b4b4)
This commit is contained in:
committed by
Andrew Scott
parent
4b5571c324
commit
376b71ea1c
@@ -110,12 +110,22 @@ export class RegistrationComponent {
|
||||
}
|
||||
```
|
||||
|
||||
A field is considered "empty" when:
|
||||
A field is considered "empty" when its value is one of the following, and non-empty for every other
|
||||
value — including `0` and the empty array `[]`:
|
||||
|
||||
| Condition | Example |
|
||||
| ------------------------ | ------- |
|
||||
| Value is `null` | `null`, |
|
||||
| Value is an empty string | `''` |
|
||||
| Condition | Example |
|
||||
| ------------------------ | ----------- |
|
||||
| Value is `null` | `null` |
|
||||
| Value is `undefined` | `undefined` |
|
||||
| Value is an empty string | `''` |
|
||||
| Value is `false` | `false` |
|
||||
| Value is `NaN` | `NaN` |
|
||||
|
||||
The last two are worth calling out:
|
||||
|
||||
- `false` is empty to follow the native semantics of `required` on `<input type="checkbox">`, where
|
||||
an unchecked box fails validation.
|
||||
- `NaN` is empty because it is usually the result of a parsing error, and is not a valid number.
|
||||
|
||||
For conditional requirements, use the `when` option:
|
||||
|
||||
@@ -130,7 +140,7 @@ registrationForm = form(this.registrationModel, (schemaPath) => {
|
||||
|
||||
The validation rule only runs when the `when` function returns `true`.
|
||||
|
||||
Note: `required` treats an empty array as present (valid), so use [`minLength()`](#minlength-and-maxlength) to enforce a minimum number of array items; it treats `false` as missing (invalid), matching `<input type="checkbox" required>`.
|
||||
Note: `required` treats an empty array as present (valid), so use [`minLength()`](#minlength-and-maxlength) to enforce a minimum number of array items.
|
||||
|
||||
### email()
|
||||
|
||||
@@ -505,9 +515,7 @@ interface User {
|
||||
lastName: string;
|
||||
}
|
||||
|
||||
@Component({
|
||||
/* ... */
|
||||
})
|
||||
@Component({/* ... */})
|
||||
export class UserFormComponent {
|
||||
readonly userModel = model<User>({
|
||||
firstName: '',
|
||||
@@ -750,9 +758,7 @@ import {Component, computed, signal} from '@angular/core';
|
||||
import {form, FormField, validateStandardSchema} from '@angular/forms/signals';
|
||||
import z from 'zod';
|
||||
|
||||
@Component({
|
||||
/* ... */
|
||||
})
|
||||
@Component({/* ... */})
|
||||
export class DynamicSchema {
|
||||
model = signal({document: '', type: 'dni'});
|
||||
|
||||
|
||||
@@ -17,6 +17,14 @@ import {requiredError} from './validation_errors';
|
||||
* This function can only be called on any type of path.
|
||||
* In addition to binding a validator, this function adds `REQUIRED` property to the field.
|
||||
*
|
||||
* A value is considered empty when it is `null`, `undefined`, the empty string `''`, `false`, or
|
||||
* `NaN`. Every other value is considered non-empty, including `0` and the empty array `[]` — use
|
||||
* [`minLength()`](api/forms/signals/minLength) to require a minimum number of items in an array.
|
||||
*
|
||||
* `false` is empty to follow the native semantics of `required` on `<input type="checkbox">`, where
|
||||
* an unchecked box fails validation. `NaN` is empty because it is usually the result of a parsing
|
||||
* error, and is not a valid number.
|
||||
*
|
||||
* @param path Path of the field to validate
|
||||
* @param config Optional, allows providing any of the following options:
|
||||
* - `message`: A user-facing message for the error.
|
||||
|
||||
@@ -12,6 +12,58 @@ import {form, required} from '../../../../public_api';
|
||||
import {requiredError} from '../../../../src/api/rules/validation/validation_errors';
|
||||
|
||||
describe('required validator', () => {
|
||||
// Documented on `required()` and in guide/forms/signals/validation#required. `false` follows the
|
||||
// native semantics of `required` on `<input type="checkbox">`; `NaN` is not a valid number.
|
||||
describe('emptiness', () => {
|
||||
it('treats null, empty string, false and NaN as empty', () => {
|
||||
const model = signal<{
|
||||
nullable: string | null;
|
||||
text: string;
|
||||
checkbox: boolean;
|
||||
num: number;
|
||||
}>({nullable: null, text: '', checkbox: false, num: Number.NaN});
|
||||
const f = form(
|
||||
model,
|
||||
(p) => {
|
||||
required(p.nullable);
|
||||
required(p.text);
|
||||
required(p.checkbox);
|
||||
required(p.num);
|
||||
},
|
||||
{injector: TestBed.inject(Injector)},
|
||||
);
|
||||
|
||||
expect(f.nullable().errors()).toEqual([requiredError({fieldTree: f.nullable})]);
|
||||
expect(f.text().errors()).toEqual([requiredError({fieldTree: f.text})]);
|
||||
expect(f.checkbox().errors()).toEqual([requiredError({fieldTree: f.checkbox})]);
|
||||
expect(f.num().errors()).toEqual([requiredError({fieldTree: f.num})]);
|
||||
});
|
||||
|
||||
it('treats 0, an empty array and other filled values as non-empty', () => {
|
||||
const model = signal<{
|
||||
zero: number;
|
||||
list: string[];
|
||||
checkbox: boolean;
|
||||
text: string;
|
||||
}>({zero: 0, list: [], checkbox: true, text: 'a'});
|
||||
const f = form(
|
||||
model,
|
||||
(p) => {
|
||||
required(p.zero);
|
||||
required(p.list);
|
||||
required(p.checkbox);
|
||||
required(p.text);
|
||||
},
|
||||
{injector: TestBed.inject(Injector)},
|
||||
);
|
||||
|
||||
expect(f.zero().errors()).toEqual([]);
|
||||
expect(f.list().errors()).toEqual([]);
|
||||
expect(f.checkbox().errors()).toEqual([]);
|
||||
expect(f.text().errors()).toEqual([]);
|
||||
});
|
||||
});
|
||||
|
||||
it('returns required Error when the value is not present', () => {
|
||||
const cat = signal({name: ''});
|
||||
const f = form(
|
||||
|
||||
Reference in New Issue
Block a user