Skip to content

refactor(forms): make markAsTouched() touch all descendants by default#67453

Open
leonsenft wants to merge 2 commits intoangular:mainfrom
leonsenft:sf-mark-all-as-touched
Open

refactor(forms): make markAsTouched() touch all descendants by default#67453
leonsenft wants to merge 2 commits intoangular:mainfrom
leonsenft:sf-mark-all-as-touched

Conversation

@leonsenft
Copy link
Contributor

markAsTouched() now marks all descendants as touched. In general this method is called when controls update the model. Most controls update leaf nodes, in which case this change has no effect.

Marking all descendants allows triggering validation for subsections of a form, independently from having to call submit() on the entire form.

markAsTouched() now accepts a MarkAsTouchedOptions parameter, which includes a self property. This can be used mark only the receiving field as touched: node.markAsTouched({self: true}).

`markAsTouched()` now marks all descendants as touched. In general this
method is called when controls update the model. Most controls update
leaf nodes, in which case this change has no effect.

Marking all descendants allows triggering validation for subsections of
a form, independently from having to call `submit()` on the entire form.

`markAsTouched()` now accepts a `MarkAsTouchedOptions` parameter, which
includes a `self` property. This can be used mark only the receiving
field as touched: `node.markAsTouched({self: true})`.
@leonsenft leonsenft requested a review from kirjs March 5, 2026 00:57
@leonsenft leonsenft added area: forms target: patch This PR is targeted for the next patch release forms: signals labels Mar 5, 2026
@ngbot ngbot bot modified the milestone: Backlog Mar 5, 2026
@pullapprove pullapprove bot requested a review from crisbeto March 5, 2026 00:57
* If `true`, only marks the current field as touched.
* If `false` or not provided, marks the field and all its descendants as touched.
*/
self?: boolean;
Copy link
Member

Choose a reason for hiding this comment

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

Should we call it onlySelf ?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah that's probably better. I could seemarkAsTouched({self: false}) being confusing. Does it mean descendants and not self? onlySelf is much more clear in that regard.

However, I noticed Reactive Forms uses onlySelf, but regarding whether ancestors (rather than descendants) are included. Do we mind the potential confusion, or would a name that indicates the inclusion/omission of descendants be more clear? For example markAsTouched({includeDescendants: false})

Copy link
Member

Choose a reason for hiding this comment

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

The alternative I'm thinking of skipDescendants:true (not a huge fan of negative flags).

Copy link
Contributor

Choose a reason for hiding this comment

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

AbstractControl.markAsTouched(opts?: {onlySelf: boolean}), so skipDescendants: true would be precedence, but since signal forms is a new ap, maybe that's ok?

Copy link
Contributor

Choose a reason for hiding this comment

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

while at it, maybe give the same treatment to markAsDirty in one go, as it also has this option in AbstractControl?

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

Labels

area: forms forms: signals target: patch This PR is targeted for the next patch release

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

3 participants