Skip to content

docs: add new signal forms cross field logic guide#67551

Open
bencodezen wants to merge 1 commit intoangular:mainfrom
bencodezen:docs/signal-forms-cross-field-logic
Open

docs: add new signal forms cross field logic guide#67551
bencodezen wants to merge 1 commit intoangular:mainfrom
bencodezen:docs/signal-forms-cross-field-logic

Conversation

@bencodezen
Copy link
Contributor

PR Checklist

Please check if your PR fulfills the following requirements:

PR Type

What kind of change does this PR introduce?

  • Bugfix
  • Feature
  • Code style update (formatting, local variables)
  • Refactoring (no functional changes, no api changes)
  • Build related changes
  • CI related changes
  • Documentation content changes
  • angular.dev application / infrastructure changes
  • Other... Please describe:

What is the current behavior?

Issue Number: N/A

What is the new behavior?

New cross-field logic guide for Signal Forms!

Does this PR introduce a breaking change?

  • Yes
  • No

Other information

@bencodezen bencodezen added action: review The PR is still awaiting reviews from at least one requested reviewer target: patch This PR is targeted for the next patch release area: docs Related to the documentation adev: preview labels Mar 10, 2026
@ngbot ngbot bot added this to the Backlog milestone Mar 10, 2026
@bencodezen bencodezen marked this pull request as draft March 10, 2026 17:19
@github-actions
Copy link

github-actions bot commented Mar 10, 2026

Deployed adev-preview for 8f754b7 to: https://ng-dev-previews-fw--pr-angular-angular-67551-adev-prev-2jz3jbuu.web.app

Note: As new commits are pushed to this pull request, this link is updated after the preview is rebuilt.

@bencodezen bencodezen removed the action: review The PR is still awaiting reviews from at least one requested reviewer label Mar 12, 2026
@bencodezen
Copy link
Contributor Author

Ahh sorry for the confusion @SkyZeroZx and @jnizet. I'm in the midst of revising the PR which is why I put it in draft mode (but forgot to take off the label). Appreciate the initial feedback. I'll make sure to consider the suggestions before the official review is live!

@bencodezen bencodezen force-pushed the docs/signal-forms-cross-field-logic branch from 8f104c7 to 8f754b7 Compare March 13, 2026 16:13
@bencodezen bencodezen added the action: review The PR is still awaiting reviews from at least one requested reviewer label Mar 13, 2026
@bencodezen bencodezen marked this pull request as ready for review March 13, 2026 16:13

The date range example from the previous section validates the end date against the start date. Because the rule reads `valueOf(schemaPath.startDate)`, it re-evaluates automatically whenever either date changes. In other words, a single validator is enough to keep the error state correct.

However, that single validator only places the error on the end date field. If you want both fields to show an error when the range is invalid, add a matching validation rule to each field:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it worth offering some advice/guidance here on how to think about which field you should attach the validator to? In talking to people about this topic, two main questions tend to come up:

  1. Should I put the validator on one of the two fields, or on the parent field (where i can read both values directly)?
  2. What if I want the error to show up on both fields?

My usual answer is: this choice depends on what UX you want. Put validation on the field(s) where you want the UI to show invalid state / want the error to show up. For good UX, this should be at the place where the user would most likely go to fix the error.

minLength(schemaPath.password, 8);

validate(schemaPath.confirmPassword, ({value, valueOf, stateOf}) => {
if (stateOf(schemaPath.password).invalid()) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice example!

}
```

The `stateOf()` call returns the other field's [field state](api/forms/signals/FieldState), giving you access to signals like `invalid()`, `touched()`, and `dirty()`. Because these are signals, the rule re-evaluates whenever the password field's validity changes.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe a cautionary callout here: you can read the state of other fields with stateOf, but take care not to read state which depends on your field's validation, as that creates a cycle.

You can't, for example, add a validator which checks whether the parent field is valid, because the parent's validity depends on its children's validity, which includes your validator.


The examples so far use `validate()` to add an error to the field being validated. But sometimes the error belongs on a _different_ field. For example, a shipping form might need to restrict shipping methods based on package weight — the validation logic needs both fields, but the error should appear on the shipping method field.

`validateTree` handles this by letting you specify which field receives the error:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This particular example is better served by validate + valueOf, I think. validateTree is more for situations when:

  • you need to perform some higher level validation of a part of the model
  • that validation may return errors that you want to show in specific places

For example, suppose I'm building a Sudoku puzzle form. It'd be really awkward to set up the whole 9x9 board with individual field validators which read surrounding fields with valueOf. It'd also be challenging to deduplicate errors in that case, and expensive because each validator would be checking the same conditions on its own.

validateTree lets me define validation logic that happens for the whole board and then decides which errors to show and on which fields. It's especially useful if you have existing APIs (like a Sudoku library) that provide this validation - you can easily run those at the top level and map the results to specific errors on specific fields.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

action: review The PR is still awaiting reviews from at least one requested reviewer adev: preview area: docs Related to the documentation target: patch This PR is targeted for the next patch release

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants