Skip to content

Commit a2337f7

Browse files
committed
docs: add global form state signals to signal forms guide
Add a new section for 'Form State Signals' in the signal forms essential guide. This documents global signals such as dirty(), valid(), invalid(), pending(), and touched() at the form level, as requested in issue angular#69544. Fixes angular#69544
1 parent d109cc5 commit a2337f7

1 file changed

Lines changed: 31 additions & 27 deletions

File tree

‎adev/src/content/introduction/essentials/signal-forms.md‎

Lines changed: 31 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -22,16 +22,17 @@ const loginModel = signal<LoginData>({
2222
});
2323
```
2424

25-
### 2. Pass the form model to `form()` to create a `FieldTree`
25+
### 2. Create a `FieldTree` with `form()`
2626

27-
Then, you pass your form model into the `form()` function to create a **field tree** - an object structure that mirrors your model's shape, allowing you to access fields with dot notation:
27+
Then, you pass your form model into the `form()` function to create a **field tree** - an object structure that mirrors your model's shape, allowing you to access fields with dot notation.
28+
29+
Both the root form object and its nested properties are `FieldTree` nodes:
2830

2931
```ts
3032
const loginForm = form(loginModel);
3133

32-
// Access fields directly by property name
33-
loginForm.email;
34-
loginForm.password;
34+
// loginForm is a FieldTree
35+
// loginForm.email is also a FieldTree
3536
```
3637

3738
### 3. Bind HTML inputs with `[formField]` directive
@@ -47,18 +48,20 @@ As a result, user changes (such as typing in the field) automatically updates th
4748

4849
NOTE: The `[formField]` directive also syncs field state for attributes like `required`, `disabled`, and `readonly` when appropriate.
4950

50-
### 4. Read field values with `value()`
51+
### 4. Read state with `FieldTree` signals
5152

52-
You can access field state by calling the field as a function. This returns a `FieldState` object containing reactive signals for the field's value, validation status, and interaction state:
53+
You can access state for any part of the tree by calling the `FieldTree` node as a function. This returns a state object containing reactive signals for the value, validation status, and interaction state:
5354

5455
```ts
55-
loginForm.email(); // Returns FieldState with value(), valid(), touched(), etc.
56+
loginForm(); // Returns state for the whole form
57+
loginForm.email(); // Returns state for the email field
5658
```
5759

58-
To read the field's current value, access the `value()` signal:
60+
To read the current value, access the `value()` signal:
5961

6062
```html
61-
<!-- Render form value that updates automatically as user types -->
63+
<!-- Render values that update automatically as user types -->
64+
<p>Form value: {{ loginForm().value() | json }}</p>
6265
<p>Email: {{ loginForm.email().value() }}</p>
6366
```
6467

@@ -67,9 +70,9 @@ To read the field's current value, access the `value()` signal:
6770
const currentEmail = loginForm.email().value();
6871
```
6972

70-
### 5. Update field values with `set()`
73+
### 5. Update values with `set()`
7174

72-
You can programmatically update a field's value using the `value.set()` method. This updates both the field and the underlying model signal:
75+
You can programmatically update values using the `value.set()` method on any node. This updates both the `FieldTree` and the underlying model signal:
7376

7477
```ts
7578
// Update the value programmatically
@@ -235,7 +238,22 @@ required(schemaPath.email, {message: 'Email is required'});
235238
email(schemaPath.email, {message: 'Please enter a valid email address'});
236239
```
237240

238-
Each form field exposes its validation state through signals. For example, you can check `field().valid()` to see if validation passes, `field().touched()` to see if the user has interacted with it, and `field().errors()` to get the list of validation errors.
241+
Each node in the `FieldTree` exposes its validation and interaction state through reactive signals.
242+
243+
### FieldTree State Signals
244+
245+
Every node in the tree, including the root form object, provides the same signals to track its state. Since every node is a `FieldTree`, the API for monitoring validity and interaction is identical at every level.
246+
247+
| State | Description |
248+
| ------------ | ------------------------------------------------------------------------------- |
249+
| `valid()` | Returns `true` if the node passes all validation rules |
250+
| `invalid()` | Returns `true` if there are validation errors |
251+
| `pending()` | Returns `true` if async validation is in progress |
252+
| `touched()` | Returns `true` if the user has focused and blurred the field or any child field |
253+
| `dirty()` | Returns `true` if the value has been changed by the user |
254+
| `disabled()` | Returns `true` if the node is disabled |
255+
| `readonly()` | Returns `true` if the node is readonly |
256+
| `errors()` | Returns an array of validation errors with `kind` and `message` properties |
239257

240258
Here's a complete example:
241259

@@ -245,20 +263,6 @@ Here's a complete example:
245263
<docs-code header="app.css" path="adev/src/content/examples/signal-forms/src/login-validation/app/app.css"/>
246264
</docs-code-multifile>
247265

248-
### Field State Signals
249-
250-
Every `field()` provides these state signals:
251-
252-
| State | Description |
253-
| ------------ | -------------------------------------------------------------------------- |
254-
| `valid()` | Returns `true` if the field passes all validation rules |
255-
| `touched()` | Returns `true` if the user has focused and blurred the field |
256-
| `dirty()` | Returns `true` if the user has changed the value |
257-
| `disabled()` | Returns `true` if the field is disabled |
258-
| `readonly()` | Returns `true` if the field is readonly |
259-
| `pending()` | Returns `true` if async validation is in progress |
260-
| `errors()` | Returns an array of validation errors with `kind` and `message` properties |
261-
262266
## Next steps
263267

264268
To learn more about Signal Forms and how it works, check out the in-depth guides:

0 commit comments

Comments
 (0)