Skip to content

fix(datepicker): emit null instead of undefined when the input is cleared - #6833

Open
mnkprs wants to merge 1 commit into
valor-software:developmentfrom
mnkprs:fix/datepicker-signal-forms-null
Open

mnkprs wants to merge 1 commit into
valor-software:developmentfrom
mnkprs:fix/datepicker-signal-forms-null

Conversation

@mnkprs

@mnkprs mnkprs commented Sep 12, 2026

Copy link
Copy Markdown

PR Checklist

Before creating new PR, please take a look at checklist below to make sure that you've done everything that needs to be done before we can merge it.

  • read and followed the CONTRIBUTING.md guide.
  • built and tested the changes locally.
  • added/updated tests.
  • N/A - no public API changes, so no API documentation updates needed.
  • N/A - no new/changed demos needed; existing reactive-forms and signal-forms usage is unaffected other than the cleared-value type.

Root cause

BsDatepickerInputDirective and BsDaterangepickerInputDirective call their registered
onChange (the value accessor callback) with undefined whenever the input is cleared -
either by typing/deleting the text and blurring, or via the picker's own clear action, which
routes through the same bsValueChange subscription.

Angular's new Signal Forms (@angular/forms/signals) treats a model property that is
explicitly set to undefined as "this field no longer exists" and deletes the corresponding
FieldNode (FieldNodeStructure.computeChildrenMap). Once that happens, any further access to
the field - including FormField's own state computed (this.field()()) - throws:

TypeError: this.field(...) is not a function

...and the field can never be updated again, exactly as reported in #6832.

Change

Emit null instead of undefined from the CVA onChange callback whenever the datepicker or
daterangepicker input is cleared (both the native change event path and the picker-driven
bsValueChange path, for both directives). null is the conventional "empty" sentinel already
used by FormControl's own default, by this library's own timepicker (onChange(null) on an
invalid/empty entry), and by Angular Material's datepicker. Internal state (_value, the public
bsValue input, writeValue, validate) is unchanged; only the value handed to the form is
normalized at the point it's emitted.

Angular/components applied the identical fix for the same Signal Forms failure mode in
angular/components#33708 (chip listbox
deselection).

Tests

Added src/datepicker/testing/bs-datepicker-input.spec.ts covering both directives:

  • Reactive forms: clearing the native input, and clearing via bsValue (the picker's own clear
    path), both now leave control.value as null rather than undefined, for bsDatepicker and
    bsDaterangepicker.
  • Signal forms: binding [formField] to a bsDatepicker input and clearing it no longer throws
    this.field(...) is not a function, the field's model value becomes null, and the field stays
    alive so a subsequently selected date still reaches the model.

All new specs fail against the current development code (reproducing #6832, including the
exact error message) and pass with this change.

Validation:

  • npx nx test datepicker: 57 passed, 2 skipped.
  • npm test -- --parallel=2 --runInBand: all 24 projects passed.
  • npx nx lint datepicker and npm run lint -- --parallel=2: all 46 projects passed, 0 errors
    (pre-existing, unrelated warnings only).
  • npx nx build datepicker --configuration=production: passed.

Behavioral note

Consumers reading the cleared value from ngModel/FormControl/[formField] now receive
null instead of undefined. This only affects the "cleared" case; a date value is unaffected.

Fixes #6832

…ared

Clearing the datepicker or daterangepicker input passed undefined to the
form's onChange callback. Signal forms treats an undefined model property as
a removed field, so [formField] crashed with "this.field(...) is not a
function" and the field could never be updated again. Emit null, matching
FormControl, the timepicker and Material's datepicker.

Closes valor-software#6832
@mnkprs
mnkprs force-pushed the fix/datepicker-signal-forms-null branch from 5f7687b to 7cb0bb5 Compare September 12, 2026 17:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

v22 Date picker with signal forms - error on clear

1 participant