From 71d676876d6d815478f590e78afe8047d3cad101 Mon Sep 17 00:00:00 2001 From: agonzalez97 Date: Mon, 25 Apr 2022 10:12:55 +0200 Subject: [PATCH] [Major] Error behaviour when empty string in textarea --- .../textarea-properties.component.html | 19 +++++--- .../textarea-preview.component.html | 8 +++- .../dxc-textarea/dxc-textarea.component.html | 6 ++- .../dxc-textarea.component.spec.ts | 28 +++++++---- .../dxc-textarea/dxc-textarea.component.ts | 46 ++++++++++--------- 5 files changed, 68 insertions(+), 39 deletions(-) diff --git a/projects/dxc-ngx-cdk-site/src/app/components/examples/textarea/textarea-properties/textarea-properties.component.html b/projects/dxc-ngx-cdk-site/src/app/components/examples/textarea/textarea-properties/textarea-properties.component.html index 66f9bdbca..8c9f939f3 100644 --- a/projects/dxc-ngx-cdk-site/src/app/components/examples/textarea/textarea-properties/textarea-properties.component.html +++ b/projects/dxc-ngx-cdk-site/src/app/components/examples/textarea/textarea-properties/textarea-properties.component.html @@ -22,7 +22,8 @@ defaultValue: string - Default value given to the textarea when is uncontrolled and also maintains the uncontrolled behaviour. + Default value given to the textarea when is uncontrolled and also + maintains the uncontrolled behaviour. @@ -59,8 +60,9 @@ If true, the input will be optional, showing (Optional) - next to the label. Otherwise, the field will be considered required and an error - will be passed as a parameter to the OnBlur and onChange functions when it has not been filled. + next to the label. Otherwise, the field will be considered required and an + error will be passed as a parameter to the OnBlur and onChange functions + when it has not been filled. @@ -94,9 +96,12 @@ error: string - If it is defined, the component will change its appearance, showing the - error below the textarea component. If it is not defined, the error - messages will be created and managed internally. + If it is a defined value and also a truthy string, the component will + change its appearance, showing the error below the textarea. If the + defined value is an empty string, it will reserve a space below the + component for a future error, but it would not change its look. In case of + being undefined or null, both the appearance and the space for the error + message would not be modified. @@ -198,4 +203,4 @@ ... - \ No newline at end of file + diff --git a/projects/dxc-ngx-cdk-site/src/app/pages/theme-builder/previews/textarea-preview/textarea-preview.component.html b/projects/dxc-ngx-cdk-site/src/app/pages/theme-builder/previews/textarea-preview/textarea-preview.component.html index 3cf4d0042..68830694e 100644 --- a/projects/dxc-ngx-cdk-site/src/app/pages/theme-builder/previews/textarea-preview/textarea-preview.component.html +++ b/projects/dxc-ngx-cdk-site/src/app/pages/theme-builder/previews/textarea-preview/textarea-preview.component.html @@ -7,20 +7,24 @@ [pattern]="pattern" (onBlur)="onBlur($event)" tabIndexValue="3" + margin="xsmall" > - + + - + + diff --git a/projects/dxc-ngx-cdk/src/lib/dxc-textarea/dxc-textarea.component.html b/projects/dxc-ngx-cdk/src/lib/dxc-textarea/dxc-textarea.component.html index 308cd4448..24cd6d50e 100644 --- a/projects/dxc-ngx-cdk/src/lib/dxc-textarea/dxc-textarea.component.html +++ b/projects/dxc-ngx-cdk/src/lib/dxc-textarea/dxc-textarea.component.html @@ -19,4 +19,8 @@ (focus)="handleOnFocus()" [attr.autocomplete]="autocomplete" > -{{ error }} +{{ error }} diff --git a/projects/dxc-ngx-cdk/src/lib/dxc-textarea/dxc-textarea.component.spec.ts b/projects/dxc-ngx-cdk/src/lib/dxc-textarea/dxc-textarea.component.spec.ts index 0c59550dd..a323bf20c 100644 --- a/projects/dxc-ngx-cdk/src/lib/dxc-textarea/dxc-textarea.component.spec.ts +++ b/projects/dxc-ngx-cdk/src/lib/dxc-textarea/dxc-textarea.component.spec.ts @@ -131,9 +131,15 @@ describe("DxcTextareaComponent", () => { expect(textarea).toHaveFocus(); fireEvent.click(textarea); fireEvent.input(textarea, { target: { value: "pattern4&" } }); - expect(onChange).toHaveBeenCalledWith({ error: null, value: "pattern4&" }); + expect(onChange).toHaveBeenCalledWith({ + error: undefined, + value: "pattern4&", + }); fireEvent.blur(textarea); - expect(onBlur).toHaveBeenCalledWith({ error: null, value: "pattern4&" }); + expect(onBlur).toHaveBeenCalledWith({ + error: undefined, + value: "pattern4&", + }); expect(screen.getByDisplayValue("pattern4&")); }); test("Strict mode - Length constraint", async () => { @@ -176,7 +182,10 @@ describe("DxcTextareaComponent", () => { fireEvent.input(textarea, { target: { value: "test 2" } }); fireEvent.blur(textarea); await waitFor(() => { - expect(onBlur).toHaveBeenCalledWith({ error: null, value: "test 2" }); + expect(onBlur).toHaveBeenCalledWith({ + error: undefined, + value: "test 2", + }); }); }); test("Strict mode - Pattern and length constraints", async () => { @@ -227,7 +236,7 @@ describe("DxcTextareaComponent", () => { fireEvent.click(textarea); fireEvent.input(textarea, { target: { value: "test 4" } }); fireEvent.blur(textarea); - expect(onBlur).toHaveBeenCalledWith({ error: null, value: "test 4" }); + expect(onBlur).toHaveBeenCalledWith({ error: undefined, value: "test 4" }); }); test("Non Strict mode - Pattern constraint", async () => { const onChange = jest.fn((value) => { @@ -351,7 +360,10 @@ describe("DxcTextareaComponent", () => { fireEvent.input(textarea, { target: { value: "Blur test" } }); fireEvent.blur(textarea); expect(onBlur).toHaveBeenCalled(); - expect(onBlur).toHaveBeenCalledWith({ value: "Blur test", error: null }); + expect(onBlur).toHaveBeenCalledWith({ + value: "Blur test", + error: undefined, + }); }); test("Controlled textarea", async () => { const onChange = jest.fn(); @@ -382,13 +394,13 @@ describe("DxcTextareaComponent", () => { expect(screen.getByDisplayValue("test")); expect(onChange).toHaveBeenCalledWith({ value: "Controlled test", - error: null, + error: undefined, }); }); fireEvent.blur(textarea); await waitFor(() => { expect(onBlur).toHaveBeenCalled(); - expect(onBlur).toHaveBeenCalledWith({ value: "test", error: null }); + expect(onBlur).toHaveBeenCalledWith({ value: "test", error: undefined }); }); }); test("Uncontrolled input", async () => { @@ -415,7 +427,7 @@ describe("DxcTextareaComponent", () => { expect(onChange).toHaveBeenCalled(); expect(onChange).toHaveBeenCalledWith({ value: "Uncontrolled test", - error: null, + error: undefined, }); expect(textarea.value).toBe("Uncontrolled test"); }); diff --git a/projects/dxc-ngx-cdk/src/lib/dxc-textarea/dxc-textarea.component.ts b/projects/dxc-ngx-cdk/src/lib/dxc-textarea/dxc-textarea.component.ts index 861e15bfb..a203a356b 100644 --- a/projects/dxc-ngx-cdk/src/lib/dxc-textarea/dxc-textarea.component.ts +++ b/projects/dxc-ngx-cdk/src/lib/dxc-textarea/dxc-textarea.component.ts @@ -68,7 +68,7 @@ export class DxcTextareaComponent implements OnInit { } private _disabled = false; /** - * If true, the textarea will be optional, showing (Optional) next to the label. + * If true, the textarea will be optional, showing (Optional) next to the label. * Otherwise, the field will be considered required and an error will be passed as a parameter to the OnBlur and onChange functions when it has not been filled. */ @Input() @@ -99,8 +99,12 @@ export class DxcTextareaComponent implements OnInit { @Input() verticalGrow: "auto" | "manual" | "none" = "auto"; /** - * If it is defined, the component will change its appearance, showing the error below the textarea component. - * If it is not defined, the error messages will be created and managed internally. + * If it is a defined value and also a truthy string, the component will + * change its appearance, showing the error below the textarea. If the defined + * value is an empty string, it will reserve a space below the component for a + * future error, but it would not change its look. In case of being undefined + * or null, both the appearance and the space for the error message would not + * be modified. */ @Input() error = undefined; @@ -110,34 +114,34 @@ export class DxcTextareaComponent implements OnInit { @Input() placeholder = ""; /** - * Regular expression that defines the valid format allowed by the textarea. - * This will be checked when the textarea loses the focus. - * If the value entered does not match the pattern, the onBlur function will be called with the value - * entered and the error informing that the value does not match the pattern as parameters. If the pattern is accomplished, + * Regular expression that defines the valid format allowed by the textarea. + * This will be checked when the textarea loses the focus. + * If the value entered does not match the pattern, the onBlur function will be called with the value + * entered and the error informing that the value does not match the pattern as parameters. If the pattern is accomplished, * the error parameter will be null. */ @Input() pattern = ""; /** - * Specifies the minimun length allowed by the textarea. - * This will be checked both when the input element loses the focus and while typing within it. - * If the string entered does not comply the minimum length, the onBlur and onChange functions will be called - * with the current value and an internal error informing that the value length does not comply the specified range. + * Specifies the minimun length allowed by the textarea. + * This will be checked both when the input element loses the focus and while typing within it. + * If the string entered does not comply the minimum length, the onBlur and onChange functions will be called + * with the current value and an internal error informing that the value length does not comply the specified range. * If a valid length is reached, the error parameter of both events will be null. */ @Input() minLength: number; /** - * Specifies the maximum length allowed by the textarea. - * This will be checked both when the input element loses the focus and while typing within it. - * If the string entered does not comply the maximum length, the onBlur and onChange functions will be called - * with the current value and an internal error informing that the value length does not comply the specified range. + * Specifies the maximum length allowed by the textarea. + * This will be checked both when the input element loses the focus and while typing within it. + * If the string entered does not comply the maximum length, the onBlur and onChange functions will be called + * with the current value and an internal error informing that the value length does not comply the specified range. * If a valid length is reached, the error parameter of both events will be null. */ @Input() maxLength: number; /** - * Size of the margin to be applied to the component ('xxsmall' | 'xsmall' | 'small' | 'medium' | 'large' | 'xlarge' | 'xxlarge'). + * Size of the margin to be applied to the component ('xxsmall' | 'xsmall' | 'small' | 'medium' | 'large' | 'xlarge' | 'xxlarge'). * You can pass an object with 'top', 'bottom', 'left' and 'right' properties in order to specify different margin sizes. */ @Input() @@ -161,7 +165,7 @@ export class DxcTextareaComponent implements OnInit { private controlled: boolean; defaultInputs = new BehaviorSubject({ placeholder: "", - error: "", + error: undefined, optional: false, disabled: false, helperText: "", @@ -175,13 +179,13 @@ export class DxcTextareaComponent implements OnInit { verticalGrow: "auto", }); /** - * This event will emit when the user types within the textarea. An object including the new value and the error will be passed to this function. + * This event will emit when the user types within the textarea. An object including the new value and the error will be passed to this function. * An example of this object is: { value: value, error: error }. If there is no error, error will be null. */ @Output() onChange = new EventEmitter(); /** - * This event will emit when the textarea loses the focus. An object including the textarea value and the error will be passed to this function. + * This event will emit when the textarea loses the focus. An object including the textarea value and the error will be passed to this function. * An example of this object is: { value: value, error: error }. If there is no error, error will be null. */ @Output() @@ -275,7 +279,7 @@ export class DxcTextareaComponent implements OnInit { return `Min length ${this.minLength}, Max length ${this.maxLength}`; if (value && !this.patternMatch(this.pattern, value)) return `Please use a valid pattern`; - return null; + return undefined; } private handleValidationError() { const validationError = this.validateValue(this.value); @@ -315,4 +319,4 @@ export class DxcTextareaComponent implements OnInit { } } } -} \ No newline at end of file +}