Skip to content

[Signal Forms] Update min and max to operate on number and Date values#68001

Open
leonsenft wants to merge 3 commits intoangular:mainfrom
leonsenft:sf-min-max-date
Open

[Signal Forms] Update min and max to operate on number and Date values#68001
leonsenft wants to merge 3 commits intoangular:mainfrom
leonsenft:sf-min-max-date

Conversation

@leonsenft
Copy link
Copy Markdown
Contributor

  • Remove string support from min and max validation rules. This is no longer necessary since FormField can bind a numeric field to a text based control.
  • Add Date support to min and max validation rules.

The `min` and `max` validation rules previously handled `string` values
to accommodate numbers bound to text inputs. However, this is no longer
necessary as the control binding itself handles the conversion.

This change removes string support from these rules, simplifying the
types to `number | null`. The validation logic has been updated to use
concrete checks (`value === null || Number.isNaN(value)`) to ensure safe
TypeScript narrowing.

Associated tests have been updated to:
- Remove string-specific validation checks.
- Add coverage for text input bindings.
- Add coverage for empty input handling (standard behavior where empty
  sets model to null and skips validation).

BREAKING CHANGE: `min` and `max` validation rules no longer support
string values. Bound values must be numbers or null.
@leonsenft leonsenft requested a review from alxhub April 2, 2026 18:29
@leonsenft leonsenft added area: forms target: patch This PR is targeted for the next patch release forms: signals labels Apr 2, 2026
@ngbot ngbot bot added this to the Backlog milestone Apr 2, 2026
@pullapprove pullapprove bot requested review from AndrewKushnir April 2, 2026 18:30
@angular-robot angular-robot bot added the detected: breaking change PR contains a commit with a breaking change label Apr 2, 2026
Extend `min` and `max` validation rules support `Date` objects in
addition to numbers.

- Update `min` and `max` validation rules to compare `Date` values.
- Introduce `LimitValue<T>` utility type to resolve limits to `Date`,
  `number`, or `Date | number` based on the value type.
- Make `FormUiControl` generic to allow custom controls to strictly type
  their `min`/`max` inputs based on their value type.

Fix angular#65676.
@leonsenft leonsenft added target: minor This PR is targeted for the next minor release and removed target: patch This PR is targeted for the next patch release labels Apr 2, 2026

constructor(
readonly min: number,
readonly min: number | Date,
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Hmm, this is unfortunate - now, in templates, you can't rely on instanceof MinValidationError giving you type-safe access to the min property. How about splitting to MinNumberValidationError and MinDateValidationError?

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.

Each with a unique kind?

export class MinNumberValidationError extends BaseNgValidationError {
  override readonly kind = 'minNumber';

  constructor(readonly min: number, options?: ValidationErrorOptions) {
    super(options);
  }
}

export class MinNumberValidationError extends BaseNgValidationError {
  override readonly kind = 'minDate';

  constructor(readonly min: Date, options?: ValidationErrorOptions) {
    super(options);
  }
}

That way switching on kind works too:

if (e instanceof NgValidationError) {
  switch(e.kind) {
    case 'minNumber':
      console.log('This is a number: ', e.min);
      break;
    case 'minDate':
      console.log('This is a date: ', e.min);
      break;
    ...
  }
}

Also thoughts are keeping "min" to represent number, as opposed to "minNumber"?

@pullapprove pullapprove bot requested a review from JeanMeche April 2, 2026 20:35
@leonsenft leonsenft requested a review from alxhub April 2, 2026 22:09

await fixture.whenStable();

const component = fixture.componentInstance;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Shouldn't this test also check that the max attribute is set on the input element ?

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.

Validation and property bindings are distinct behaviors that are tested separately. For context, binding to the input max property doesn't have affect signal forms validation–it would however affect native validation.

See the previous test : should bind to native control.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Then perharps should we add a test case that illustrate that we are setting the min/max attribute for date inputs ?

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.

Yes, good catch. This actually raises an interesting issue.

We made the decision that max and min only worked on Date values for dates. Attempting to use Date objects to set the value implicitly converts them to strings.

For example:

input.max = new Date('2026-04-02'); // Wed Apr 02 2026 [detailed time zone information]

However, date inputs only accept very specific formats for min and max: https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Attributes/max#syntax.

For example:

// type="date" expects yyyy-mm-dd
input.max = '2026-04-02';

Several ideas come to mind:

  • Add specific logic for binding min and max based on the input type, converting dates to their corresponding strings.
  • Change min and max to use string instead of Date for date inputs, since that's what they expect. We'd then need to add specific logic to the validation rules to handle comparing Date objects with strings. Furthermore we'd need to change the metadata reducers to handle comparing dates as strings.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I think at one point we might have considered a separate validator minDate/maxDate. Would that still be on the table ?

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.

Yes, I think especially so in light of this issue.

Copy link
Copy Markdown
Contributor

@jnizet jnizet left a comment

Choose a reason for hiding this comment

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

I like my date input fields to be bound to iso date strings (which is the default native value of date inputs). Iso dates lexicographic order is also the chronological order. Can't min and max be applied to them?

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

Labels

area: forms detected: breaking change PR contains a commit with a breaking change forms: signals target: minor This PR is targeted for the next minor release

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

4 participants