Skip to content

feat(forms): support imperative disable and enable in SignalFormControl#69683

Open
franmc01 wants to merge 1 commit into
angular:mainfrom
franmc01:fix-signal-form-control-disable
Open

feat(forms): support imperative disable and enable in SignalFormControl#69683
franmc01 wants to merge 1 commit into
angular:mainfrom
franmc01:fix-signal-form-control-disable

Conversation

@franmc01

@franmc01 franmc01 commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

PR Checklist

PR Type

  • 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?

SignalFormControl.disable() and enable() throw. Because FormGroup.disable() calls disable() on every child, a group or array containing a SignalFormControl cannot be disabled at all. reset({value, disabled}) also throws.

Issue Number: #68882

What is the new behavior?

  • disable() / enable() work, both directly and from a parent FormGroup / FormArray.
  • The imperative status is applied through a root-level disabled rule on the control's internal schema, so status, enabled, parent value exclusion, and onDisabledChange callbacks derive from the existing signal forms machinery.
  • enable() only clears the imperatively set status; a control disabled by a schema disabled rule stays disabled.
  • Boxed reset({value, disabled}) is supported instead of throwing.
  • Disabling a dirty/touched control recalculates parent pristine/touched state without resetting siblings, matching reactive forms.
  • emitEvent: false is honored for the control's own status emissions.
  • Migration guide updated.

Not done in this PR: extending AbstractControl<T> for a typed value (also requested in #68882). That changes the typed public API surface and is left as a follow-up.

Does this PR introduce a breaking change?

  • Yes
  • No

Other information

Fixes #68882

@pullapprove pullapprove Bot requested a review from crisbeto July 8, 2026 17:29
@google-cla

This comment was marked as outdated.

@angular-robot angular-robot Bot added detected: feature PR contains a feature commit area: forms labels Jul 8, 2026
@ngbot ngbot Bot added this to the Backlog milestone Jul 8, 2026
Previously SignalFormControl threw when disable() or enable() was called,
which made it impossible to disable a FormGroup or FormArray containing
one, since the parent's disable() calls disable({onlySelf: true}) on
every child control.

The imperative disabled status is bridged through signal forms' own rule
system: the user schema is wrapped with a root-level disabled rule driven
by an internal signal that disable(), enable(), and boxed reset() write.
Status, enabled, parent value exclusion, and onDisabledChange callbacks
all derive from the existing machinery.

enable() only clears the imperatively set status; a control disabled by a
schema rule stays disabled. Boxed reset({value, disabled}) is supported
instead of throwing. Parent pristine and touched recalculation mirrors
reactive forms via _updatePristine and _updateTouched so sibling state is
never reset, and the control's own status emissions honor emitEvent:
false through last-emitted-status deduplication.

Fixes angular#68882
@franmc01 franmc01 force-pushed the fix-signal-form-control-disable branch from 444fd06 to d9db3b1 Compare July 8, 2026 17:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: forms detected: feature PR contains a feature commit

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Allow disable in SignalFormControl

1 participant