diff --git a/packages/forms/src/directives/validators.ts b/packages/forms/src/directives/validators.ts index 566e0167ac..53b53d2450 100644 --- a/packages/forms/src/directives/validators.ts +++ b/packages/forms/src/directives/validators.ts @@ -167,7 +167,7 @@ export const MAX_VALIDATOR: StaticProvider = { selector: 'input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]', providers: [MAX_VALIDATOR], - host: {'[attr.max]': 'max ? max : null'} + host: {'[attr.max]': 'max ?? null'} }) export class MaxValidator extends AbstractValidatorDirective implements OnChanges { /** @@ -227,7 +227,7 @@ export const MIN_VALIDATOR: StaticProvider = { selector: 'input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]', providers: [MIN_VALIDATOR], - host: {'[attr.min]': 'min ? min : null'} + host: {'[attr.min]': 'min ?? null'} }) export class MinValidator extends AbstractValidatorDirective implements OnChanges { /** diff --git a/packages/forms/test/reactive_integration_spec.ts b/packages/forms/test/reactive_integration_spec.ts index 99de565ea2..b75e4c3e13 100644 --- a/packages/forms/test/reactive_integration_spec.ts +++ b/packages/forms/test/reactive_integration_spec.ts @@ -2558,8 +2558,23 @@ const ValueAccessorB = createControlValueAccessor('[cva-b]'); fixture.componentInstance.max = 1; fixture.detectChanges(); + expect(input.getAttribute('max')).toEqual('1'); expect(form.valid).toBeFalse(); expect(form.controls.pin.errors).toEqual({max: {max: 1, actual: 2}}); + + fixture.componentInstance.min = 0; + fixture.componentInstance.max = 0; + fixture.detectChanges(); + expect(input.getAttribute('min')).toEqual('0'); + expect(input.getAttribute('max')).toEqual('0'); + expect(form.valid).toBeFalse(); + expect(form.controls.pin.errors).toEqual({max: {max: 0, actual: 2}}); + + input.value = 0; + dispatchEvent(input, 'input'); + fixture.detectChanges(); + expect(form.valid).toBeTruthy(); + expect(form.controls.pin.errors).toBeNull(); }); it('should validate max for float number', () => { @@ -2573,6 +2588,7 @@ const ValueAccessorB = createControlValueAccessor('[cva-b]'); const input = fixture.debugElement.query(By.css('input')).nativeElement; const form = fixture.componentInstance.form; + expect(input.getAttribute('max')).toEqual('10.35'); expect(input.value).toEqual('10.25'); expect(form.valid).toBeTruthy(); expect(form.controls.pin.errors).toBeNull(); @@ -2586,6 +2602,7 @@ const ValueAccessorB = createControlValueAccessor('[cva-b]'); fixture.componentInstance.max = 10.05; fixture.detectChanges(); + expect(input.getAttribute('max')).toEqual('10.05'); expect(form.valid).toBeFalse(); expect(form.controls.pin.errors).toEqual({max: {max: 10.05, actual: 10.15}}); @@ -2618,6 +2635,7 @@ const ValueAccessorB = createControlValueAccessor('[cva-b]'); fixture.componentInstance.max = 1; fixture.detectChanges(); + expect(input.getAttribute('max')).toEqual('1'); expect(form.valid).toBeFalse(); expect(form.controls.pin.errors).toEqual({max: {max: 1, actual: 2}}); }); @@ -2644,8 +2662,23 @@ const ValueAccessorB = createControlValueAccessor('[cva-b]'); fixture.componentInstance.min = 5; fixture.detectChanges(); + expect(input.getAttribute('min')).toEqual('5'); expect(form.valid).toBeFalse(); expect(form.controls.pin.errors).toEqual({min: {min: 5, actual: 2}}); + + fixture.componentInstance.min = 0; + input.value = -5; + dispatchEvent(input, 'input'); + fixture.detectChanges(); + expect(input.getAttribute('min')).toEqual('0'); + expect(form.valid).toBeFalse(); + expect(form.controls.pin.errors).toEqual({min: {min: 0, actual: -5}}); + + input.value = 0; + dispatchEvent(input, 'input'); + fixture.detectChanges(); + expect(form.valid).toBeTruthy(); + expect(form.controls.pin.errors).toBeNull(); }); it('should validate min for float number', () => { @@ -2660,6 +2693,8 @@ const ValueAccessorB = createControlValueAccessor('[cva-b]'); const input = fixture.debugElement.query(By.css('input')).nativeElement; const form = fixture.componentInstance.form; + expect(input.getAttribute('min')).toEqual('10.25'); + expect(input.getAttribute('max')).toEqual('10.5'); expect(input.value).toEqual('10.25'); expect(form.valid).toBeTruthy(); expect(form.controls.pin.errors).toBeNull(); @@ -2672,6 +2707,7 @@ const ValueAccessorB = createControlValueAccessor('[cva-b]'); fixture.componentInstance.min = 10.40; fixture.detectChanges(); + expect(input.getAttribute('min')).toEqual('10.4'); expect(form.valid).toBeFalse(); expect(form.controls.pin.errors).toEqual({min: {min: 10.40, actual: 10.35}}); @@ -2704,6 +2740,7 @@ const ValueAccessorB = createControlValueAccessor('[cva-b]'); fixture.componentInstance.min = 5; fixture.detectChanges(); + expect(input.getAttribute('min')).toEqual('5'); expect(form.valid).toBeFalse(); expect(form.controls.pin.errors).toEqual({min: {min: 5, actual: 2}}); }); diff --git a/packages/forms/test/template_integration_spec.ts b/packages/forms/test/template_integration_spec.ts index 859c25f9e8..8270270ceb 100644 --- a/packages/forms/test/template_integration_spec.ts +++ b/packages/forms/test/template_integration_spec.ts @@ -1524,6 +1524,7 @@ import {NgModelCustomComp, NgModelCustomWrapper} from './value_accessor_integrat input.value = ''; dispatchEvent(input, 'input'); fixture.detectChanges(); + expect(input.getAttribute('max')).toEqual('10'); expect(form.valid).toEqual(true); expect(form.controls.max.errors).toBeNull(); @@ -1538,6 +1539,21 @@ import {NgModelCustomComp, NgModelCustomWrapper} from './value_accessor_integrat fixture.detectChanges(); expect(form.valid).toEqual(true); expect(form.controls.max.errors).toBeNull(); + + fixture.componentInstance.max = 0; + fixture.detectChanges(); + tick(); + dispatchEvent(input, 'input'); + fixture.detectChanges(); + expect(input.getAttribute('max')).toEqual('0'); + expect(form.valid).toEqual(false); + expect(form.controls.max.errors).toEqual({max: {max: 0, actual: 9}}); + + input.value = 0; + dispatchEvent(input, 'input'); + fixture.detectChanges(); + expect(form.valid).toEqual(true); + expect(form.controls.max.errors).toBeNull(); })); it('should validate max for float number', fakeAsync(() => { @@ -1552,6 +1568,7 @@ import {NgModelCustomComp, NgModelCustomWrapper} from './value_accessor_integrat input.value = ''; dispatchEvent(input, 'input'); fixture.detectChanges(); + expect(input.getAttribute('max')).toEqual('10.25'); expect(form.valid).toEqual(true); expect(form.controls.max.errors).toBeNull(); @@ -1586,6 +1603,7 @@ import {NgModelCustomComp, NgModelCustomWrapper} from './value_accessor_integrat input.value = '11'; dispatchEvent(input, 'input'); fixture.detectChanges(); + expect(input.getAttribute('max')).toEqual('10'); expect(form.valid).toEqual(false); expect(form.controls.max.errors).toEqual({max: {max: 10, actual: 11}}); @@ -1635,6 +1653,7 @@ import {NgModelCustomComp, NgModelCustomWrapper} from './value_accessor_integrat input.value = ''; dispatchEvent(input, 'input'); fixture.detectChanges(); + expect(input.getAttribute('min')).toEqual('10'); expect(form.valid).toEqual(true); expect(form.controls.min.errors).toBeNull(); @@ -1649,6 +1668,22 @@ import {NgModelCustomComp, NgModelCustomWrapper} from './value_accessor_integrat fixture.detectChanges(); expect(form.valid).toEqual(false); expect(form.controls.min.errors).toEqual({min: {min: 10, actual: 9}}); + + fixture.componentInstance.min = 0; + fixture.detectChanges(); + tick(); + input.value = -5; + dispatchEvent(input, 'input'); + fixture.detectChanges(); + expect(input.getAttribute('min')).toEqual('0'); + expect(form.valid).toEqual(false); + expect(form.controls.min.errors).toEqual({min: {min: 0, actual: -5}}); + + input.value = 0; + dispatchEvent(input, 'input'); + fixture.detectChanges(); + expect(form.valid).toEqual(true); + expect(form.controls.min.errors).toBeNull(); })); it('should validate min for float number', fakeAsync(() => { @@ -1663,6 +1698,7 @@ import {NgModelCustomComp, NgModelCustomWrapper} from './value_accessor_integrat input.value = ''; dispatchEvent(input, 'input'); fixture.detectChanges(); + expect(input.getAttribute('min')).toEqual('10.25'); expect(form.valid).toEqual(true); expect(form.controls.min.errors).toBeNull(); @@ -1696,6 +1732,7 @@ import {NgModelCustomComp, NgModelCustomWrapper} from './value_accessor_integrat input.value = '11'; dispatchEvent(input, 'input'); fixture.detectChanges(); + expect(input.getAttribute('min')).toEqual('10'); expect(form.valid).toEqual(true); expect(form.controls.min.errors).toBeNull();