Skip to content

Commit 76d699b

Browse files
committed
fixup! feat(forms): introduce min and max validators
1 parent 1e03920 commit 76d699b

File tree

4 files changed

+86
-10
lines changed

4 files changed

+86
-10
lines changed

goldens/public-api/forms/forms.d.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -338,7 +338,7 @@ export declare class MaxLengthValidator implements Validator, OnChanges {
338338
}
339339

340340
export declare class MaxValidator extends AbstractValidatorDirective implements OnChanges {
341-
max: string;
341+
max: string | number;
342342
ngOnChanges(changes: SimpleChanges): void;
343343
}
344344

@@ -350,7 +350,7 @@ export declare class MinLengthValidator implements Validator, OnChanges {
350350
}
351351

352352
export declare class MinValidator extends AbstractValidatorDirective implements OnChanges {
353-
min: string;
353+
min: string | number;
354354
ngOnChanges(changes: SimpleChanges): void;
355355
}
356356

packages/forms/src/directives/validators.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,7 @@ export class MaxValidator extends AbstractValidatorDirective implements OnChange
174174
* @description
175175
* Tracks changes to the max bound to this directive.
176176
*/
177-
@Input() max!: string;
177+
@Input() max!: string|number;
178178
/** @internal */
179179
inputName = 'max';
180180
/** @internal */
@@ -234,7 +234,7 @@ export class MinValidator extends AbstractValidatorDirective implements OnChange
234234
* @description
235235
* Tracks changes to the min bound to this directive.
236236
*/
237-
@Input() min!: string;
237+
@Input() min!: string|number;
238238
/** @internal */
239239
inputName = 'min';
240240
/** @internal */

packages/forms/test/reactive_integration_spec.ts

Lines changed: 41 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2478,6 +2478,43 @@ const ValueAccessorB = createControlValueAccessor('[cva-b]');
24782478
expect(maxValidateFnSpy).toHaveBeenCalled();
24792479
});
24802480

2481+
it('should run min/max validation when constraints are represented as strings', () => {
2482+
const fixture = initTest(getComponent(dir));
2483+
const control = new FormControl(5);
2484+
2485+
// Run tests when min and max are defined as strings.
2486+
fixture.componentInstance.min = '1';
2487+
fixture.componentInstance.max = '10';
2488+
2489+
fixture.componentInstance.control = control;
2490+
fixture.componentInstance.form = new FormGroup({'pin': control});
2491+
fixture.detectChanges();
2492+
2493+
const input = fixture.debugElement.query(By.css('input')).nativeElement;
2494+
const form = fixture.componentInstance.form;
2495+
2496+
expect(input.value).toEqual('5');
2497+
expect(form.valid).toBeTruthy();
2498+
expect(form.controls.pin.errors).toBeNull();
2499+
2500+
input.value = 2; // inside [1, 10] range
2501+
dispatchEvent(input, 'input');
2502+
expect(form.value).toEqual({pin: 2});
2503+
expect(form.valid).toBeTruthy();
2504+
expect(form.controls.pin.errors).toBeNull();
2505+
2506+
input.value = -2; // outside [1, 10] range
2507+
dispatchEvent(input, 'input');
2508+
expect(form.value).toEqual({pin: -2});
2509+
expect(form.valid).toBeFalse();
2510+
expect(form.controls.pin.errors).toEqual({min: {min: 1, actual: -2}});
2511+
2512+
input.value = 20; // outside [1, 10] range
2513+
dispatchEvent(input, 'input');
2514+
expect(form.valid).toBeFalse();
2515+
expect(form.controls.pin.errors).toEqual({max: {max: 10, actual: 20}});
2516+
});
2517+
24812518
it('should run min/max validation for negative values', () => {
24822519
const fixture = initTest(getComponent(dir));
24832520
const control = new FormControl(-30);
@@ -4640,8 +4677,8 @@ class NgForFormControlWithValidators {
46404677
class MinMaxFormControlNameComp {
46414678
control!: FormControl;
46424679
form!: FormGroup;
4643-
min: number = 1;
4644-
max: number = 10;
4680+
min: number|string = 1;
4681+
max: number|string = 10;
46454682
}
46464683

46474684
@Component({
@@ -4654,6 +4691,6 @@ class MinMaxFormControlNameComp {
46544691
class MinMaxFormControlComp {
46554692
control!: FormControl;
46564693
form!: FormGroup;
4657-
min: number = 1;
4658-
max: number = 10;
4694+
min: number|string = 1;
4695+
max: number|string = 10;
46594696
}

packages/forms/test/template_integration_spec.ts

Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1755,6 +1755,45 @@ import {NgModelCustomComp, NgModelCustomWrapper} from './value_accessor_integrat
17551755
expect(minValidateFnSpy).not.toHaveBeenCalled();
17561756
}));
17571757

1758+
['number', 'string'].forEach((inputType: string) => {
1759+
it(`should validate min and max when constraints are represented using a ${inputType}`,
1760+
fakeAsync(() => {
1761+
const fixture = initTest(NgModelMinMaxValidator);
1762+
1763+
fixture.componentInstance.min = inputType === 'string' ? '5' : 5;
1764+
fixture.componentInstance.max = inputType === 'string' ? '10' : 10;
1765+
1766+
fixture.detectChanges();
1767+
tick();
1768+
1769+
const input = fixture.debugElement.query(By.css('input')).nativeElement;
1770+
const form = fixture.debugElement.children[0].injector.get(NgForm);
1771+
1772+
input.value = '';
1773+
dispatchEvent(input, 'input');
1774+
fixture.detectChanges();
1775+
expect(form.valid).toEqual(true);
1776+
expect(form.controls.min_max.errors).toBeNull();
1777+
1778+
input.value = 11;
1779+
dispatchEvent(input, 'input');
1780+
fixture.detectChanges();
1781+
expect(form.valid).toEqual(false);
1782+
expect(form.controls.min_max.errors).toEqual({max: {max: 10, actual: 11}});
1783+
1784+
input.value = 4;
1785+
dispatchEvent(input, 'input');
1786+
fixture.detectChanges();
1787+
expect(form.valid).toEqual(false);
1788+
expect(form.controls.min_max.errors).toEqual({min: {min: 5, actual: 4}});
1789+
1790+
input.value = 9;
1791+
dispatchEvent(input, 'input');
1792+
fixture.detectChanges();
1793+
expect(form.valid).toEqual(true);
1794+
expect(form.controls.min_max.errors).toBeNull();
1795+
}));
1796+
});
17581797
it('should validate min and max', fakeAsync(() => {
17591798
const fixture = initTest(NgModelMinMaxValidator);
17601799
fixture.componentInstance.min = 5;
@@ -2319,8 +2358,8 @@ class NgModelMinValidator {
23192358
<form><input name="min_max" type="number" ngModel [min]="min" [max]="max"></form>`
23202359
})
23212360
class NgModelMinMaxValidator {
2322-
min!: number;
2323-
max!: number;
2361+
min!: number|string;
2362+
max!: number|string;
23242363
}
23252364

23262365
@Directive({selector: '[myDir]'})

0 commit comments

Comments
 (0)