[Signal Forms] Update min and max to operate on number and Date values#68001
[Signal Forms] Update min and max to operate on number and Date values#68001leonsenft wants to merge 3 commits intoangular:mainfrom
min and max to operate on number and Date values#68001Conversation
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.
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.
b3c23ef to
7e32650
Compare
|
|
||
| constructor( | ||
| readonly min: number, | ||
| readonly min: number | Date, |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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"?
|
|
||
| await fixture.whenStable(); | ||
|
|
||
| const component = fixture.componentInstance; |
There was a problem hiding this comment.
Shouldn't this test also check that the max attribute is set on the input element ?
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
Then perharps should we add a test case that illustrate that we are setting the min/max attribute for date inputs ?
There was a problem hiding this comment.
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
minandmaxbased on the inputtype, converting dates to their corresponding strings. - Change
minandmaxto usestringinstead ofDatefor 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.
There was a problem hiding this comment.
I think at one point we might have considered a separate validator minDate/maxDate. Would that still be on the table ?
There was a problem hiding this comment.
Yes, I think especially so in light of this issue.
jnizet
left a comment
There was a problem hiding this comment.
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?
stringsupport fromminandmaxvalidation rules. This is no longer necessary sinceFormFieldcan bind a numeric field to a text based control.Datesupport tominandmaxvalidation rules.