UNPKG

@engie-group/fluid-design-system-angular

Version:

Fluid Design System Angular

307 lines (264 loc) 6.23 kB
import {CommonModule} from '@angular/common'; import { AfterContentInit, ChangeDetectionStrategy, Component, ContentChild, EventEmitter, Input, Output, ViewEncapsulation, } from '@angular/core'; import {FormFieldDirective} from '../form-field/form-field.directive'; import {IconButtonComponent} from '../icon-button/icon-button.component'; import {IconComponent} from '../icon/icon.component'; import {FormItemSize} from './form-item.model'; @Component({ selector: 'nj-form-item', templateUrl: './form-item.component.html', styleUrls: ['./form-item.component.scss'], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, standalone: true, imports: [IconComponent, IconButtonComponent, FormFieldDirective, CommonModule] }) export class FormItemComponent implements AfterContentInit { private readonly formItemClassName = 'nj-form-item'; /** * @ignore */ private _hasError: boolean; /** * @ignore */ private _hasSuccess: boolean; /** * @ignore */ private _hasHint: boolean; /** * @ignore */ isPassword: boolean; /** * @ignore */ isVisible = false; /** * @ignore */ passwordNotice = ''; /** * @ignore */ passwordButtonLabel = ''; /** * @ignore */ isMultiline = false; /** * Input id and label for attribute, needed for focus to work properly */ @Input() inputId: string; /** * Form item size */ @Input() size: FormItemSize = 'medium'; /** * Whether the form-item label is floating */ @Input() isFloatingLabel = true; /** * Whether form-item is disabled or not */ @Input() isDisabled: boolean; /** * Whether form-item is required or not */ @Input() isRequired: boolean; /** * Whether form-item is in success state */ @Input() set hasSuccess(value: boolean) { this._hasSuccess = value; this.setAriaAttributes(); } get hasSuccess(): boolean { return this._hasSuccess; } /** * Whether form-item is in error state */ @Input() set hasError(value: boolean) { this._hasError = value; this.setAriaAttributes(); } get hasError(): boolean { return this._hasError; } /** * Whether the form-item has a hint substring */ @Input() set hasHint(value: boolean) { this._hasHint = value; this.setAriaAttributes(); } get hasHint(): boolean { return this._hasHint; } /** * Whether the form-item has a custom icon */ @Input() hasCustomIcon: boolean; /** * Whether the form-item's icon (or custom icon) is clickable */ @Input() isIconClickable = true; /** * Material icon name */ @Input() iconName: string; /** * Additional form-item css classes */ @Input() additionalClass: string = ''; /** * Label for the button to toggle password visibility when password is hidden. * @example "Show password" */ @Input() passwordButtonLabelShow?: string; /** * Label for the button to toggle password visibility when password is visible. * @example "Hide password" */ @Input() passwordButtonLabelHide?: string; /** * Label to announce when password becomes visible. * @example "Password is visible" */ @Input() passwordNoticeIsVisible?: string; /** * Label to announce when password becomes hidden. * @example "Password is hidden" */ @Input() passwordNoticeIsHidden?: string; /** * Whether form-item is a select or not */ @Input() isSelect: boolean; /** * Outputs icon click */ @Output() iconClick: EventEmitter<MouseEvent> = new EventEmitter< MouseEvent >(); /** * Outputs icon keydown */ @Output() iconKeydown: EventEmitter<KeyboardEvent> = new EventEmitter< KeyboardEvent >(); /** * Outputs icon click */ @Output() wrapperClick: EventEmitter<MouseEvent> = new EventEmitter< MouseEvent >(); /** * @ignore */ @ContentChild(FormFieldDirective) formField: FormFieldDirective; ngAfterContentInit() { const tagName = this.formField?.tagName?.toLowerCase(); this.isPassword = this.formField?.type === 'password'; this.isMultiline = tagName === 'textarea'; this.passwordButtonLabel = this.passwordButtonLabelShow; this.setAriaAttributes(); if (this.isRequired) { this.formField.element.setAttribute('required', 'required'); } } /** * @ignore */ iconClickHandler(event: MouseEvent) { if (!this.isIconClickable) { return; } this.iconClick.emit(event); } /** * @ignore */ iconKeydownHandler(event: KeyboardEvent) { event?.preventDefault(); if (!this.isIconClickable) { return; } this.iconKeydown.emit(event); } /** * @ignore */ toggleVisibility() { if (this.isVisible) { this.formField.type = 'password'; this.passwordNotice = this.passwordNoticeIsHidden; this.passwordButtonLabel = this.passwordButtonLabelShow; } else { this.formField.type = 'text'; this.passwordNotice = this.passwordNoticeIsVisible; this.passwordButtonLabel = this.passwordButtonLabelHide; } this.isVisible = !this.isVisible; } /** * @ignore */ getSubscriptId(): string { return `${this.inputId}-subscript`; } /** * @ignore */ setAriaAttributes() { if (this.formField?.element) { if (this.hasError) { this.formField.element.setAttribute('aria-invalid', 'true'); } if (this.hasError || this.hasSuccess || this.hasHint) { this.formField.element.setAttribute('aria-describedby', this.getSubscriptId()); } } } /** * @ignore */ isCustomSelect(): boolean { const type = this.formField?.type; return this.isSelect && type === 'text'; } /** * @ignore */ getFormItemSizeClass(): string { let sizeModifier: string; switch (this.size) { case 'small': sizeModifier = 'sm'; break; case 'large': sizeModifier = 'lg'; break; case 'xlarge': sizeModifier = 'xl'; break; default: break; } return sizeModifier ? `${this.formItemClassName}--${sizeModifier}` : ''; } }