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 cb9d2439a..66f9bdbca 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 @@ -59,7 +59,8 @@ If true, the input will be optional, showing (Optional) - next to the label. + 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. @@ -171,7 +172,7 @@ - size: string | object + size: string 'medium' @@ -197,4 +198,4 @@ ... - + \ No newline at end of file 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 f83cdb9cf..861e15bfb 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 @@ -20,6 +20,8 @@ import { BackgroundProviderService } from "../../public-api"; import { CssUtils } from "../utils"; import { DxcTextareaHelper } from "./dxc-textarea.helper"; import { v4 as uuidv4 } from "uuid"; +import { Space, Spacing, TextareaProperties } from "./dxc-textarea.types"; +import EmittedValue from "../dxc-text-input/emitted-value.type"; @Component({ selector: "dxc-textarea", @@ -29,25 +31,34 @@ import { v4 as uuidv4 } from "uuid"; export class DxcTextareaComponent implements OnInit { @HostBinding("class") className; @HostBinding("class.hasError") hasError = false; - + /** + * Text to be placed above the textarea. + */ @Input() - label: string; - + label: string = ""; + /** + * Name attribute of the textarea element. + */ @Input() - name: string; - + name: string = ""; + /** + * Value of the textarea. If undefined, the component will be uncontrolled and the value will be managed internally. + */ @Input() value: string; - + /** + * Default value given to the textarea when is uncontrolled and also maintains the uncontrolled behaviour. + */ @Input() defaultValue: string; - + /** + * Helper text to be placed above the textarea. + */ @Input() - id: string; - - @Input() - helperText: string; - + helperText: string = ""; + /** + * If true, the component will be disabled. + */ @Input() get disabled(): boolean { return this._disabled; @@ -56,7 +67,10 @@ export class DxcTextareaComponent implements OnInit { this._disabled = coerceBooleanProperty(value); } private _disabled = false; - + /** + * 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() get optional(): boolean { return this._optional; @@ -65,7 +79,9 @@ export class DxcTextareaComponent implements OnInit { this._optional = coerceBooleanProperty(value); } private _optional = false; - + /** + * Number of rows of the textarea. + */ @Input() get rows(): number { return this._rows; @@ -74,40 +90,76 @@ export class DxcTextareaComponent implements OnInit { this._rows = coerceNumberProperty(value); } private _rows = 4; - + /** + * Defines the textarea's ability to resize vertically. It can be: + 'auto': The textarea grows or shrinks automatically in order to fit the content. + 'manual': The height of the textarea is enabled to be manually modified. + 'none': The textarea has a fixed height and can't be modified. + */ @Input() - verticalGrow = "auto"; - + 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. + */ @Input() error = undefined; - + /** + * Text to be put as placeholder of the textarea. + */ @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, + * 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. + * 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. + * 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'). + * You can pass an object with 'top', 'bottom', 'left' and 'right' properties in order to specify different margin sizes. + */ @Input() - margin: Object | string; - + margin: Space | Spacing; + /** + * Value of the tabindex attribute. + */ @Input() - tabIndexValue: number; - + tabIndexValue: number = 0; + /** + * Size of the component ('small' | 'medium' | 'large' | 'fillParent'). + */ @Input() - size: string; - + size: "small" | "medium" | "large" | "fillParent" = "medium"; + /** + * HTML autocomplete attribute. Lets the user specify if any permission the user agent has to provide automated assistance in filling out + * the textarea value. Its value must be one of all the possible values of the HTML autocomplete attribute: 'on', 'off', 'email', 'username', 'new-password', ... + */ @Input() autocomplete: string = "off"; - private controlled: boolean; - - defaultInputs = new BehaviorSubject({ + defaultInputs = new BehaviorSubject({ placeholder: "", error: "", optional: false, @@ -116,29 +168,29 @@ export class DxcTextareaComponent implements OnInit { value: undefined, name: "", label: "", - margin: "", - tabIndexValueValue: 0, + margin: undefined, + tabIndexValue: 0, size: "medium", rows: 4, 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. + * An example of this object is: { value: value, error: error }. If there is no error, error will be null. + */ @Output() - onChange = new EventEmitter(); - + 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. + * An example of this object is: { value: value, error: error }. If there is no error, error will be null. + */ @Output() - onBlur = new EventEmitter(); - + onBlur = new EventEmitter(); @ViewChild("textareaRef", { static: true }) textareaRef: ElementRef; - darkBackground: boolean = false; - isDirty: boolean = false; - validationError: string = ""; - textareaId = `textarea-${uuidv4()}`; - constructor( private cdRef: ChangeDetectorRef, private helper: DxcTextareaHelper, @@ -158,7 +210,6 @@ export class DxcTextareaComponent implements OnInit { }, 0); }); } - ngOnChanges(changes: SimpleChanges): void { this.checkHeight(); this.hasError = this.error && !this.disabled ? true : false; @@ -172,7 +223,6 @@ export class DxcTextareaComponent implements OnInit { darkBackground: this.darkBackground, })}`; } - ngOnInit(): void { if (this.value === undefined) { this.value = this.defaultValue ?? ""; @@ -185,14 +235,12 @@ export class DxcTextareaComponent implements OnInit { darkBackground: this.darkBackground, })}`; } - ngAfterViewInit(): void { if (this.textareaRef) { this.textareaRef.nativeElement.ariaDisabled = this.disabled; } this.checkHeight(); } - handleOnChange(event) { if (this.value !== event && this.isDirty) { this.onChange.emit({ value: event, error: this.validateValue(event) }); @@ -209,20 +257,17 @@ export class DxcTextareaComponent implements OnInit { } this.cdRef.detectChanges(); } - handleOnBlur() { this.onBlur.emit({ value: this.value, error: this.handleValidationError(), }); } - handleOnFocus() { if (!this.isDirty) { this.isDirty = true; } } - private validateValue(value) { if (this.isRequired(value)) return `This field is required. Please, enter a value.`; @@ -232,27 +277,22 @@ export class DxcTextareaComponent implements OnInit { return `Please use a valid pattern`; return null; } - private handleValidationError() { const validationError = this.validateValue(this.value); this.validationError = validationError; return validationError; } - private patternMatch(pattern, value) { const patternToMatch = new RegExp(pattern); return patternToMatch.test(value); } - private isRequired = (value) => value === "" && !this.optional; - private isLengthIncorrect = (value) => (value !== "" && this.minLength && value && value.length < +this.minLength) || (this.maxLength && value && value.length > +this.maxLength); - private checkHeight() { if (this.textareaRef) { if (this.verticalGrow === "auto") { @@ -275,4 +315,4 @@ export class DxcTextareaComponent implements OnInit { } } } -} +} \ No newline at end of file diff --git a/projects/dxc-ngx-cdk/src/lib/dxc-textarea/dxc-textarea.types.ts b/projects/dxc-ngx-cdk/src/lib/dxc-textarea/dxc-textarea.types.ts new file mode 100644 index 000000000..0620d420c --- /dev/null +++ b/projects/dxc-ngx-cdk/src/lib/dxc-textarea/dxc-textarea.types.ts @@ -0,0 +1,41 @@ +export type Space = + | "xxsmall" + | "xsmall" + | "small" + | "medium" + | "large" + | "xlarge" + | "xxlarge"; + +export type Spacing = { + top?: Space; + bottom?: Space; + left?: Space; + right?: Space; +}; + +export type EmittedValue = { + value: string; + error: string; +}; + +export interface TextareaProperties { + value?: string; + defaultValue?: string; + label: string; + name?: string; + helperText?: string; + placeholder?: string; + disabled?: boolean; + optional?: boolean; + verticalGrow: "auto" | "manual" | "none"; + rows?: number; + error?: string; + pattern?: string; + minLength?: number; + maxLength?: number; + margin?: Space | Spacing; + size?: "small" | "medium" | "large" | "fillParent"; + tabIndexValue?: number; + autocomplete?: string; +}