From 1b0b36d14322a77e67a106991174db36b1c8bcd7 Mon Sep 17 00:00:00 2001 From: Fabian Wiles Date: Sat, 22 Dec 2018 13:39:37 +1300 Subject: [PATCH] fix(forms): match getError and hasError to get method signature (#20211) Internally getError and hasError call the AbstractControl#get method which takes `path: Array | string` as input, since there are different ways to traverse the AbstractControl tree. This change matches the method signitures of all methods that use this. PR Close #20211 --- .../directives/abstract_control_directive.ts | 4 +- packages/forms/src/model.ts | 6 +- packages/forms/test/form_group_spec.ts | 64 +++++++++++++++++++ tools/public_api_guard/forms/forms.d.ts | 8 +-- 4 files changed, 74 insertions(+), 8 deletions(-) diff --git a/packages/forms/src/directives/abstract_control_directive.ts b/packages/forms/src/directives/abstract_control_directive.ts index 65a0debe69..5c20cda551 100644 --- a/packages/forms/src/directives/abstract_control_directive.ts +++ b/packages/forms/src/directives/abstract_control_directive.ts @@ -177,7 +177,7 @@ export abstract class AbstractControlDirective { * * If the control is not present, false is returned. */ - hasError(errorCode: string, path?: string[]): boolean { + hasError(errorCode: string, path?: Array|string): boolean { return this.control ? this.control.hasError(errorCode, path) : false; } @@ -208,7 +208,7 @@ export abstract class AbstractControlDirective { * @returns error data for that particular error. If the control or error is not present, * null is returned. */ - getError(errorCode: string, path?: string[]): any { + getError(errorCode: string, path?: Array|string): any { return this.control ? this.control.getError(errorCode, path) : null; } } diff --git a/packages/forms/src/model.ts b/packages/forms/src/model.ts index cc649152f9..e9d41d74e1 100644 --- a/packages/forms/src/model.ts +++ b/packages/forms/src/model.ts @@ -671,7 +671,7 @@ export abstract class AbstractControl { * @returns error data for that particular error. If the control or error is not present, * null is returned. */ - getError(errorCode: string, path?: string[]): any { + getError(errorCode: string, path?: Array|string): any { const control = path ? this.get(path) : this; return control && control.errors ? control.errors[errorCode] : null; } @@ -706,7 +706,9 @@ export abstract class AbstractControl { * * If the control is not present, false is returned. */ - hasError(errorCode: string, path?: string[]): boolean { return !!this.getError(errorCode, path); } + hasError(errorCode: string, path?: Array|string): boolean { + return !!this.getError(errorCode, path); + } /** * Retrieves the top-level ancestor of this control. diff --git a/packages/forms/test/form_group_spec.ts b/packages/forms/test/form_group_spec.ts index 5b3f622070..3105c00ff1 100644 --- a/packages/forms/test/form_group_spec.ts +++ b/packages/forms/test/form_group_spec.ts @@ -684,6 +684,70 @@ import {of } from 'rxjs'; expect(g.getError('required', ['one'])).toEqual(null); expect(g.getError('required', ['invalid'])).toEqual(null); }); + + it('should be able to traverse group with single string', () => { + const c = new FormControl('', Validators.required); + const g = new FormGroup({'one': c}); + expect(c.getError('required')).toEqual(true); + expect(g.getError('required', 'one')).toEqual(true); + }); + + it('should be able to traverse group with string delimited by dots', () => { + const c = new FormControl('', Validators.required); + const g2 = new FormGroup({'two': c}); + const g1 = new FormGroup({'one': g2}); + expect(c.getError('required')).toEqual(true); + expect(g1.getError('required', 'one.two')).toEqual(true); + }); + + it('should traverse group with form array using string and numbers', () => { + const c = new FormControl('', Validators.required); + const g2 = new FormGroup({'two': c}); + const a = new FormArray([g2]); + const g1 = new FormGroup({'one': a}); + expect(c.getError('required')).toEqual(true); + expect(g1.getError('required', ['one', 0, 'two'])).toEqual(true); + }); + }); + + describe('hasError', () => { + it('should return true when it is present', () => { + const c = new FormControl('', Validators.required); + const g = new FormGroup({'one': c}); + expect(c.hasError('required')).toEqual(true); + expect(g.hasError('required', ['one'])).toEqual(true); + }); + + it('should return false otherwise', () => { + const c = new FormControl('not empty', Validators.required); + const g = new FormGroup({'one': c}); + expect(c.hasError('invalid')).toEqual(false); + expect(g.hasError('required', ['one'])).toEqual(false); + expect(g.hasError('required', ['invalid'])).toEqual(false); + }); + + it('should be able to traverse group with single string', () => { + const c = new FormControl('', Validators.required); + const g = new FormGroup({'one': c}); + expect(c.hasError('required')).toEqual(true); + expect(g.hasError('required', 'one')).toEqual(true); + }); + + it('should be able to traverse group with string delimited by dots', () => { + const c = new FormControl('', Validators.required); + const g2 = new FormGroup({'two': c}); + const g1 = new FormGroup({'one': g2}); + expect(c.hasError('required')).toEqual(true); + expect(g1.hasError('required', 'one.two')).toEqual(true); + }); + it('should traverse group with form array using string and numbers', () => { + const c = new FormControl('', Validators.required); + const g2 = new FormGroup({'two': c}); + const a = new FormArray([g2]); + const g1 = new FormGroup({'one': a}); + expect(c.getError('required')).toEqual(true); + expect(g1.getError('required', ['one', 0, 'two'])).toEqual(true); + }); }); describe('validator', () => { diff --git a/tools/public_api_guard/forms/forms.d.ts b/tools/public_api_guard/forms/forms.d.ts index b75a2aa6e8..eb334e5ec2 100644 --- a/tools/public_api_guard/forms/forms.d.ts +++ b/tools/public_api_guard/forms/forms.d.ts @@ -30,8 +30,8 @@ export declare abstract class AbstractControl { emitEvent?: boolean; }): void; get(path: Array | string): AbstractControl | null; - getError(errorCode: string, path?: string[]): any; - hasError(errorCode: string, path?: string[]): boolean; + getError(errorCode: string, path?: Array | string): any; + hasError(errorCode: string, path?: Array | string): boolean; markAsDirty(opts?: { onlySelf?: boolean; }): void; @@ -80,8 +80,8 @@ export declare abstract class AbstractControlDirective { readonly valid: boolean | null; readonly value: any; readonly valueChanges: Observable | null; - getError(errorCode: string, path?: string[]): any; - hasError(errorCode: string, path?: string[]): boolean; + getError(errorCode: string, path?: Array | string): any; + hasError(errorCode: string, path?: Array | string): boolean; reset(value?: any): void; }