Skip to content

Add framework support for binding form controls#63773

Closed
leonsenft wants to merge 5 commits intoangular:mainfrom
leonsenft:signal-forms-control
Closed

Add framework support for binding form controls#63773
leonsenft wants to merge 5 commits intoangular:mainfrom
leonsenft:signal-forms-control

Conversation

@leonsenft
Copy link
Copy Markdown
Contributor

@leonsenft leonsenft commented Sep 12, 2025

Move most of the implementation of the Control directive into core framework instructions. This allows field state changes to be propagated to their corresponding UI controls directly during execution of a template update block, instead of relying on effect()s to synchronize each change later during the update (and too late in the case of required inputs).

  • Define a private API in @angular/core for signal forms to implement:
    • ɵControl for the Control directive.
    • ɵFieldState for the control's associated FieldState.
  • Emit specialized instructions when compiling a [control] binding:
    • ɵɵcontrolCreate sets up the ɵControl directive if present, determines whether it's bound to a native control element or a custom control component, and adds the appropriate event listeners to notify the ɵFieldState of UI changes.
    • ɵɵcontrol propagates changes from ɵFieldState properties to their corresponding UI control properties (in additional to binding the control property itself).

Future changes will focus on optimizing the instructions:

  • Cache control-related information on the TNode
  • Limit which properties are updated based on the control type (e.g. only set max/min for number or date)
  • Check if bound values changed before updating their target property or input

@leonsenft leonsenft added area: core Issues related to the framework runtime area: forms target: major This PR is targeted for the next major release labels Sep 12, 2025
@leonsenft leonsenft added area: compiler Issues related to `ngc`, Angular's template compiler forms: signals labels Sep 12, 2025
@ngbot ngbot bot modified the milestone: Backlog Sep 12, 2025
@leonsenft leonsenft force-pushed the signal-forms-control branch 2 times, most recently from e205267 to 4b76845 Compare September 12, 2025 21:19
@leonsenft leonsenft marked this pull request as draft September 12, 2025 21:30
@leonsenft leonsenft marked this pull request as ready for review September 12, 2025 22:43
}

/**
* An operation that checks if a specialized control directive exists and possibly registers it to
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

nit: I'd replace possibly -> if not |if yes

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

It's more nuanced than that. The presence of the directive isn't sufficient to determine whether or not the control directive is registered/set up. I've reworded it to be more clear.

@leonsenft leonsenft requested a review from mmalerba October 2, 2025 18:41
@leonsenft leonsenft requested a review from mmalerba October 2, 2025 22:11
Copy link
Copy Markdown
Contributor

@mmalerba mmalerba left a comment

Choose a reason for hiding this comment

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

reviewed-for: public-api

* Emit a `ɵɵcontrol` instruction in place of `ɵɵproperty` for property
  bindings named "control". This instruction cannot be chained, but is
  otherwise functionally equivalent.

* Upcoming changes will use the `ɵɵcontrol` instruction to bind a signal
  form field to a UI control (be it a native element or custom directive).
Move most of the implementation of the `Control` directive into core
framework instructions. This allows field state changes to be propagated
to their corresponding UI controls directly during execution of a
template update block, instead of relying on `effect()`s to synchronize
each change later during the update (and too late in the case of
required inputs).

* Define a private API in `@angular/core` for signal forms to implement:
  * `ɵControl` for the `Control` directive.
  * `ɵFieldState` for the control's associated `FieldState`.
* Emit specialized instructions when compiling a `[control]` binding:
  * `ɵɵcontrolCreate` sets up the `ɵControl` directive if present,
    determines whether it's bound to a native control element or a
    custom control component, and adds the appropriate event listeners
    to notify the `ɵFieldState` of UI changes.
  * `ɵɵcontrol` propagates changes from `ɵFieldState` properties to their
    corresponding UI control properties (in additional to binding the `control`
    property itself).
@leonsenft leonsenft force-pushed the signal-forms-control branch from 8b1552c to 2749074 Compare October 3, 2025 17:09
@mmalerba mmalerba added the requires: TGP This PR requires a passing TGP before merging is allowed label Oct 3, 2025
@pullapprove pullapprove bot removed the requires: TGP This PR requires a passing TGP before merging is allowed label Oct 3, 2025
@leonsenft leonsenft removed the request for review from alxhub October 3, 2025 20:58
@leonsenft leonsenft added the requires: TGP This PR requires a passing TGP before merging is allowed label Oct 3, 2025
@pullapprove pullapprove bot removed the requires: TGP This PR requires a passing TGP before merging is allowed label Oct 3, 2025
@mmalerba mmalerba added the merge: caretaker note Alert the caretaker performing the merge to check the PR for an out of normal action needed or note label Oct 3, 2025
@mmalerba
Copy link
Copy Markdown
Contributor

mmalerba commented Oct 3, 2025

caretaker: wait for TGP to merge

@mmalerba mmalerba added action: global presubmit The PR is in need of a google3 global presubmit action: merge The PR is ready for merge by the caretaker labels Oct 3, 2025
@mmalerba
Copy link
Copy Markdown
Contributor

mmalerba commented Oct 4, 2025

This PR was merged into the repository. The changes were merged into the following branches:

@mmalerba mmalerba closed this in 42e1062 Oct 4, 2025
mmalerba pushed a commit that referenced this pull request Oct 4, 2025
Move most of the implementation of the `Control` directive into core
framework instructions. This allows field state changes to be propagated
to their corresponding UI controls directly during execution of a
template update block, instead of relying on `effect()`s to synchronize
each change later during the update (and too late in the case of
required inputs).

* Define a private API in `@angular/core` for signal forms to implement:
  * `ɵControl` for the `Control` directive.
  * `ɵFieldState` for the control's associated `FieldState`.
* Emit specialized instructions when compiling a `[control]` binding:
  * `ɵɵcontrolCreate` sets up the `ɵControl` directive if present,
    determines whether it's bound to a native control element or a
    custom control component, and adds the appropriate event listeners
    to notify the `ɵFieldState` of UI changes.
  * `ɵɵcontrol` propagates changes from `ɵFieldState` properties to their
    corresponding UI control properties (in additional to binding the `control`
    property itself).

PR Close #63773
napulitanfrontend pushed a commit to napulitanfrontend/angular that referenced this pull request Oct 10, 2025
…ngular#63773)

* Emit a `ɵɵcontrol` instruction in place of `ɵɵproperty` for property
  bindings named "control". This instruction cannot be chained, but is
  otherwise functionally equivalent.

* Upcoming changes will use the `ɵɵcontrol` instruction to bind a signal
  form field to a UI control (be it a native element or custom directive).

PR Close angular#63773
napulitanfrontend pushed a commit to napulitanfrontend/angular that referenced this pull request Oct 10, 2025
…ngular#63773)

* Emit a `ɵɵcontrol` instruction in place of `ɵɵproperty` for property
  bindings named "control". This instruction cannot be chained, but is
  otherwise functionally equivalent.

* Upcoming changes will use the `ɵɵcontrol` instruction to bind a signal
  form field to a UI control (be it a native element or custom directive).

PR Close angular#63773
napulitanfrontend pushed a commit to napulitanfrontend/angular that referenced this pull request Oct 10, 2025
…lar#63773)

Move most of the implementation of the `Control` directive into core
framework instructions. This allows field state changes to be propagated
to their corresponding UI controls directly during execution of a
template update block, instead of relying on `effect()`s to synchronize
each change later during the update (and too late in the case of
required inputs).

* Define a private API in `@angular/core` for signal forms to implement:
  * `ɵControl` for the `Control` directive.
  * `ɵFieldState` for the control's associated `FieldState`.
* Emit specialized instructions when compiling a `[control]` binding:
  * `ɵɵcontrolCreate` sets up the `ɵControl` directive if present,
    determines whether it's bound to a native control element or a
    custom control component, and adds the appropriate event listeners
    to notify the `ɵFieldState` of UI changes.
  * `ɵɵcontrol` propagates changes from `ɵFieldState` properties to their
    corresponding UI control properties (in additional to binding the `control`
    property itself).

PR Close angular#63773
napulitanfrontend pushed a commit to napulitanfrontend/angular that referenced this pull request Oct 11, 2025
…ngular#63773)

* Emit a `ɵɵcontrol` instruction in place of `ɵɵproperty` for property
  bindings named "control". This instruction cannot be chained, but is
  otherwise functionally equivalent.

* Upcoming changes will use the `ɵɵcontrol` instruction to bind a signal
  form field to a UI control (be it a native element or custom directive).

PR Close angular#63773
napulitanfrontend pushed a commit to napulitanfrontend/angular that referenced this pull request Oct 11, 2025
…ngular#63773)

* Emit a `ɵɵcontrol` instruction in place of `ɵɵproperty` for property
  bindings named "control". This instruction cannot be chained, but is
  otherwise functionally equivalent.

* Upcoming changes will use the `ɵɵcontrol` instruction to bind a signal
  form field to a UI control (be it a native element or custom directive).

PR Close angular#63773
napulitanfrontend pushed a commit to napulitanfrontend/angular that referenced this pull request Oct 11, 2025
…lar#63773)

Move most of the implementation of the `Control` directive into core
framework instructions. This allows field state changes to be propagated
to their corresponding UI controls directly during execution of a
template update block, instead of relying on `effect()`s to synchronize
each change later during the update (and too late in the case of
required inputs).

* Define a private API in `@angular/core` for signal forms to implement:
  * `ɵControl` for the `Control` directive.
  * `ɵFieldState` for the control's associated `FieldState`.
* Emit specialized instructions when compiling a `[control]` binding:
  * `ɵɵcontrolCreate` sets up the `ɵControl` directive if present,
    determines whether it's bound to a native control element or a
    custom control component, and adds the appropriate event listeners
    to notify the `ɵFieldState` of UI changes.
  * `ɵɵcontrol` propagates changes from `ɵFieldState` properties to their
    corresponding UI control properties (in additional to binding the `control`
    property itself).

PR Close angular#63773
@leonsenft leonsenft deleted the signal-forms-control branch October 13, 2025 21:30
@angular-automatic-lock-bot
Copy link
Copy Markdown

This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

This action has been performed automatically by a bot.

@angular-automatic-lock-bot angular-automatic-lock-bot bot locked and limited conversation to collaborators Nov 13, 2025
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

action: global presubmit The PR is in need of a google3 global presubmit action: merge The PR is ready for merge by the caretaker area: compiler Issues related to `ngc`, Angular's template compiler area: core Issues related to the framework runtime area: forms forms: signals merge: caretaker note Alert the caretaker performing the merge to check the PR for an out of normal action needed or note target: major This PR is targeted for the next major release

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

3 participants