Skip to content

Commit 9a7dedc

Browse files
cexbrayatleonsenft
authored andcommitted
docs: use when in signal forms rule examples
Update the Signal Forms guides to match df54e6a, which introduced the consistent {when: ...} form for these rules.
1 parent 2959d6b commit 9a7dedc

5 files changed

Lines changed: 47 additions & 41 deletions

File tree

adev/src/content/guide/forms/signals/designing-your-form-model.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -211,9 +211,9 @@ interface BillPayFormModel {
211211

212212
const billPaySchema = schema<BillPayFormModel>((billPay) => {
213213
// Hide credit card details when user has selected a method other than credit card.
214-
hidden(billPay.method.card, ({valueOf}) => valueOf(billPay.method.type) !== 'card');
214+
hidden(billPay.method.card, {when: ({valueOf}) => valueOf(billPay.method.type) !== 'card'});
215215
// Hide bank account details when user has selected a method other than bank account.
216-
hidden(billPay.method.bank, ({valueOf}) => valueOf(billPay.method.type) !== 'bank');
216+
hidden(billPay.method.bank, {when: ({valueOf}) => valueOf(billPay.method.type) !== 'bank'});
217217
});
218218
```
219219

@@ -358,7 +358,7 @@ class MyForm {
358358

359359
protected readonly myForm = form(this.formModel, (root) => {
360360
// Disable the entire form when the resource is loading.
361-
disabled(root, () => this.domainModelResource.isLoading());
361+
disabled(root, {when: () => this.domainModelResource.isLoading()});
362362
});
363363
}
364364
```

adev/src/content/guide/forms/signals/field-state-management.md

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -222,8 +222,8 @@ Availability state signals control whether fields are interactive, editable, or
222222
The `disabled()` signal indicates whether a field accepts user input. Disabled fields appear in the UI but users cannot interact with them.
223223

224224
```angular-ts
225-
import { Component, signal } from '@angular/core'
226-
import { form, FormField, disabled } from '@angular/forms/signals'
225+
import {Component, signal} from '@angular/core';
226+
import {form, FormField, disabled} from '@angular/forms/signals';
227227
228228
@Component({
229229
selector: 'app-order',
@@ -236,25 +236,25 @@ import { form, FormField, disabled } from '@angular/forms/signals'
236236
@if (orderForm.couponCode().disabled()) {
237237
<p class="info">Coupon code is only available for orders over $50</p>
238238
}
239-
`
239+
`,
240240
})
241241
export class Order {
242242
orderModel = signal({
243243
total: 25,
244-
couponCode: ''
245-
})
244+
couponCode: '',
245+
});
246246
247-
orderForm = form(this.orderModel, schemaPath => {
248-
disabled(schemaPath.couponCode, ({valueOf}) => valueOf(schemaPath.total) < 50)
249-
})
247+
orderForm = form(this.orderModel, (schemaPath) => {
248+
disabled(schemaPath.couponCode, {when: ({valueOf}) => valueOf(schemaPath.total) < 50});
249+
});
250250
}
251251
```
252252

253253
In this example, we use `valueOf(schemaPath.total)` to check the value of the `total` field to determine whether `couponCode` should be disabled.
254254

255255
NOTE: The schema callback parameter (`schemaPath` in these examples) is a `SchemaPathTree` object that provides paths to all fields in your form. You can name this parameter anything you like.
256256

257-
When defining rules like `disabled()`, `hidden()`, or `readonly()`, the logic callback receives a `FieldContext` object that is typically destructured (such as `({valueOf})`). Two methods commonly used in validation rules are:
257+
When defining rules like `disabled()`, `hidden()`, or `readonly()`, the `when` function receives a `FieldContext` object that is typically destructured (such as `({valueOf})`). Two methods commonly used in validation rules are:
258258

259259
- `valueOf(schemaPath.otherField)` - Read the value of another field in the form
260260
- `value()` - A signal containing the value of the field the rule is applied to
@@ -293,7 +293,7 @@ export class Profile {
293293
});
294294
295295
profileForm = form(this.profileModel, (schemaPath) => {
296-
hidden(schemaPath.publicUrl, ({valueOf}) => !valueOf(schemaPath.isPublic));
296+
hidden(schemaPath.publicUrl, {when: ({valueOf}) => !valueOf(schemaPath.isPublic)});
297297
});
298298
}
299299
```
@@ -440,7 +440,7 @@ const orderModel = signal({
440440
});
441441

442442
const orderForm = form(orderModel, (schemaPath) => {
443-
hidden(schemaPath.shippingAddress, ({valueOf}) => !valueOf(schemaPath.requiresShipping));
443+
hidden(schemaPath.shippingAddress, {when: ({valueOf}) => !valueOf(schemaPath.requiresShipping)});
444444
});
445445
```
446446

@@ -517,7 +517,9 @@ export class Order {
517517
});
518518
519519
orderForm = form(this.orderModel, (schemaPath) => {
520-
hidden(schemaPath.shippingAddress, ({valueOf}) => !valueOf(schemaPath.requiresShipping));
520+
hidden(schemaPath.shippingAddress, {
521+
when: ({valueOf}) => !valueOf(schemaPath.requiresShipping),
522+
});
521523
});
522524
}
523525
```

adev/src/content/guide/forms/signals/form-logic.md

Lines changed: 27 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,12 @@ Use rules when field behavior depends on other field values or needs to update r
1414

1515
## How rules work
1616

17-
Rules bind reactive logic to specific fields in your form. Most rules accept a reactive logic function as an optional argument. The reactive logic function automatically recomputes whenever the signals it references change, just like a `computed`.
17+
Rules bind reactive logic to specific fields in your form. Most conditional rules accept an options object with a `when` function. The `when` function automatically recomputes whenever the signals it references change, just like a `computed`.
1818

1919
```ts
2020
const orderForm = form(this.orderModel, (schemaPath) => {
21-
disabled(schemaPath.couponCode, ({valueOf}) => valueOf(schemaPath.total) < 50);
22-
//~~~~~~ ~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
21+
disabled(schemaPath.couponCode, {when: ({valueOf}) => valueOf(schemaPath.total) < 50});
22+
//~~~~~~ ~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2323
//rule path reactive logic function
2424
});
2525
```
@@ -70,7 +70,7 @@ export class Settings {
7070

7171
### Conditional disabling
7272

73-
To disable a field based on conditions, provide a reactive logic function that returns `true` (disabled) or `false` (enabled):
73+
To disable a field based on conditions, provide a `when` function that returns `true` (disabled) or `false` (enabled):
7474

7575
```angular-ts
7676
import {Component, signal} from '@angular/core';
@@ -98,7 +98,7 @@ export class Order {
9898
});
9999
100100
orderForm = form(this.orderModel, (schemaPath) => {
101-
disabled(schemaPath.couponCode, ({valueOf}) => valueOf(schemaPath.total) < 50);
101+
disabled(schemaPath.couponCode, {when: ({valueOf}) => valueOf(schemaPath.total) < 50});
102102
});
103103
}
104104
```
@@ -143,14 +143,15 @@ export class Order {
143143
});
144144
145145
orderForm = form(this.orderModel, (schemaPath) => {
146-
disabled(schemaPath.couponCode, ({valueOf}) =>
147-
valueOf(schemaPath.total) < 50 ? 'Order must be $50 or more to use a coupon' : false,
148-
);
146+
disabled(schemaPath.couponCode, {
147+
when: ({valueOf}) =>
148+
valueOf(schemaPath.total) < 50 ? 'Order must be $50 or more to use a coupon' : false,
149+
});
149150
});
150151
}
151152
```
152153

153-
The reactive logic function returns:
154+
The `when` function returns:
154155

155156
- A **string** to disable the field with a reason
156157
- `false` to enable the field (not just any falsy value - use `false` explicitly)
@@ -163,12 +164,13 @@ You can also call `disabled()` multiple times on the same field, and all of the
163164

164165
```angular-ts
165166
orderForm = form(this.orderModel, (schemaPath) => {
166-
disabled(schemaPath.promoCode, ({valueOf}) =>
167-
!valueOf(schemaPath.hasAccount) ? 'You must have an account to use promo codes' : false,
168-
);
169-
disabled(schemaPath.promoCode, ({valueOf}) =>
170-
valueOf(schemaPath.total) < 25 ? 'Order must be at least $25' : false,
171-
);
167+
disabled(schemaPath.promoCode, {
168+
when: ({valueOf}) =>
169+
!valueOf(schemaPath.hasAccount) ? 'You must have an account to use promo codes' : false,
170+
});
171+
disabled(schemaPath.promoCode, {
172+
when: ({valueOf}) => (valueOf(schemaPath.total) < 25 ? 'Order must be at least $25' : false),
173+
});
172174
});
173175
```
174176

@@ -184,7 +186,7 @@ NOTE: Like disabled fields, hidden fields also skip validation. See the [Validat
184186

185187
### Basic field hiding
186188

187-
Use `hidden()` with a reactive logic function that returns `true` (hidden) or `false` (visible):
189+
Use `hidden()` with a `when` function that returns `true` (hidden) or `false` (visible):
188190

189191
```angular-ts
190192
import {Component, signal} from '@angular/core';
@@ -214,7 +216,7 @@ export class Profile {
214216
});
215217
216218
profileForm = form(this.profileModel, (schemaPath) => {
217-
hidden(schemaPath.publicUrl, ({valueOf}) => !valueOf(schemaPath.isPublic));
219+
hidden(schemaPath.publicUrl, {when: ({valueOf}) => !valueOf(schemaPath.isPublic)});
218220
});
219221
}
220222
```
@@ -264,7 +266,7 @@ The `[FormField]` directive automatically binds the `readonly` attribute based o
264266

265267
### Conditional readonly
266268

267-
To make a field readonly based on conditions, provide a reactive logic function:
269+
To make a field readonly based on conditions, provide a `when` function:
268270

269271
```angular-ts
270272
import {Component, signal} from '@angular/core';
@@ -292,7 +294,7 @@ export class Document {
292294
});
293295
294296
documentForm = form(this.documentModel, (schemaPath) => {
295-
readonly(schemaPath.title, ({valueOf}) => valueOf(schemaPath.isLocked));
297+
readonly(schemaPath.title, {when: ({valueOf}) => valueOf(schemaPath.isLocked)});
296298
});
297299
}
298300
```
@@ -580,10 +582,12 @@ export class Promo {
580582
});
581583
582584
promoForm = form(this.promoModel, (schemaPath) => {
583-
disabled(schemaPath.promoCode, ({valueOf}) =>
584-
!valueOf(schemaPath.hasAccount) ? 'You must have an account' : false,
585-
);
586-
hidden(schemaPath.promoCode, ({valueOf}) => valueOf(schemaPath.subscriptionType) === 'free');
585+
disabled(schemaPath.promoCode, {
586+
when: ({valueOf}) => (!valueOf(schemaPath.hasAccount) ? 'You must have an account' : false),
587+
});
588+
hidden(schemaPath.promoCode, {
589+
when: ({valueOf}) => valueOf(schemaPath.subscriptionType) === 'free',
590+
});
587591
debounce(schemaPath.promoCode, 300);
588592
metadata(schemaPath.promoCode, PLACEHOLDER, () => 'Enter promo code');
589593
});

adev/src/content/guide/forms/signals/migration.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -347,7 +347,7 @@ export class UserProfile {
347347

348348
readonly emailControl = new SignalFormControl('', (p) => {
349349
// The control becomes disabled whenever isLoading is true
350-
disabled(p, () => this.isLoading());
350+
disabled(p, {when: () => this.isLoading()});
351351
});
352352

353353
async saveData() {

adev/src/content/guide/forms/signals/schemas.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,13 @@ Signal Forms uses a two-layer architecture to separate _how your form is structu
44

55
When you pass a schema function to `form()`, that function _runs once_ during form creation. Its job is to set up the form's logic tree by declaring which fields have validation, which fields are disabled, and which fields depend on other fields. This is the **structural layer** of your form.
66

7-
Inside a schema function, you call rule functions such as `disabled()` and `validate()`. These rule functions accept reactive logic that recomputes whenever the signals they reference change. Other rules like `required()` accept optional configuration, including a `when` function that conditionally activates the rule. Together, these form the **behavioral layer** of your form during runtime.
7+
Inside a schema function, you call rule functions such as `disabled()` and `validate()`. These rule functions accept reactive logic that recomputes whenever the signals they reference change. Conditional rules like `disabled()` and `required()` accept optional configuration, including a `when` function that activates the rule. Together, these form the **behavioral layer** of your form during runtime.
88

99
```ts
1010
contactForm = form(this.contactModel, (schemaPath) => {
1111
// Schema function: runs ONCE during form creation
1212
required(schemaPath.name);
13-
disabled(schemaPath.couponCode, ({valueOf}) => valueOf(schemaPath.total) < 50);
13+
disabled(schemaPath.couponCode, {when: ({valueOf}) => valueOf(schemaPath.total) < 50});
1414
// ^^^ Reactive logic: recomputes when total changes
1515
});
1616
```

0 commit comments

Comments
 (0)