import { CommonModule } from '@angular/common'; import { AfterViewInit, CUSTOM_ELEMENTS_SCHEMA, ChangeDetectionStrategy, ChangeDetectorRef, Component, ElementRef, EventEmitter, Input, OnDestroy, OnInit, Output, Self, TemplateRef, ViewChild, ViewEncapsulation, } from '@angular/core'; import { ControlValueAccessor, FormsModule, NgControl, ReactiveFormsModule, } from '@angular/forms'; import { combineLatest, Subject, takeUntil } from 'rxjs'; import { AngularSvgIconModule } from 'angular-svg-icon'; // models import { ICaInput } from './config'; import { LabelColor, CommandsEvent } from './models'; // pipes import { InputErrorPipe, InputContainerClassPipe, InputClassPipe, LabelClassPipe, ShowClearPipe, ShowInvalidDangerMarkPipe, ShowValidCheckPipe, InputTypePipe, InputDropdownArrowClassPipe, ShowDropdownArrowPipe, InputPlaceholderIconRightClassPipe, InputPlaceholderTextClassPipe, ShowPlaceholderTextPipe, } from './pipes'; import { CaSvgPipe } from '../../pipes/ca-svg.pipe'; import { LoadStatusColorPipe } from '../../pipes/load-status-color.pipe'; import { ThousandSeparatorPipe } from '../../pipes/thousand-separator.pipe'; // components import { CaAppTooltipV2Component } from '../ca-app-tooltip-v2/ca-app-tooltip-v2.component'; import { CaInputClearComponent } from './components/ca-input-clear/ca-input-clear.component'; import { CaInputCommandsComponent } from './components/ca-input-commands/ca-input-commands.component'; import { CaInputPasswordComponent } from './components/ca-input-password/ca-input-password.component'; import { CaInputPlaceholderIconComponent } from './components/ca-input-placeholder-icon/ca-input-placeholder-icon.component'; import { CaProfileImageComponent } from '../ca-profile-image/ca-profile-image.component'; import { CaLoadModalProgressBarComponent } from '../ca-load-modal-progress-bar/ca-load-modal-progress-bar.component'; // services import { CaInputValidationService } from './services'; import { CalendarDateTimePickerService } from '../ca-custom-datetime-pickers/services/calendar-datetime-picker.service'; // helpers import { InputChangeValue, InputSvgRoutes } from './utils'; // modules import { NgbModule, NgbPopover } from '@ng-bootstrap/ng-bootstrap'; import { NgxMaskModule } from 'ngx-mask'; // directives import { MinMaxValueDirective } from './directives'; // enums import { InputCommandsType, InputStringEnum } from './enums'; import { DropdownTemplateTypeEnum } from '../ca-input-dropdown/enums'; import { CaInputBaseComponent } from './base-classes/ca-input-base'; import { EventInputManager } from './base-classes/ca-input-event-manager'; @Component({ selector: 'app-ca-input', templateUrl: './ca-input.component.html', styleUrls: ['./ca-input.component.scss'], encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, imports: [ // Module CommonModule, FormsModule, ReactiveFormsModule, AngularSvgIconModule, NgbModule, NgxMaskModule, // Pipe InputErrorPipe, InputContainerClassPipe, InputClassPipe, LabelClassPipe, ShowClearPipe, ShowInvalidDangerMarkPipe, ShowValidCheckPipe, InputTypePipe, InputDropdownArrowClassPipe, ShowDropdownArrowPipe, CaSvgPipe, LoadStatusColorPipe, InputPlaceholderIconRightClassPipe, InputPlaceholderTextClassPipe, ShowPlaceholderTextPipe, // Components CaInputClearComponent, CaAppTooltipV2Component, CaInputPasswordComponent, CaInputPlaceholderIconComponent, CaInputCommandsComponent, CaProfileImageComponent, CaLoadModalProgressBarComponent, // Directives MinMaxValueDirective, ], schemas: [CUSTOM_ELEMENTS_SCHEMA], providers: [CalendarDateTimePickerService] }) export class CaInputComponent extends CaInputBaseComponent implements OnInit, OnDestroy, AfterViewInit, ControlValueAccessor { @ViewChild('input', { static: true }) public input!: ElementRef; @ViewChild(NgbPopover) ngbMainPopover!: NgbPopover; @ViewChild(CaInputPlaceholderIconComponent) caInputPlaceholderIconComponent!: CaInputPlaceholderIconComponent; public _inputConfig!: ICaInput; @Input() set inputConfig(config: ICaInput) { this._inputConfig = config; this.onInputConfigChange(); } @Input() dateTimePopover!: TemplateRef; @Input() incorrectValue!: boolean; @Input() selectedDropdownLabelColor!: LabelColor | null; @Input() template!: string; @Output('handleToggleDropdownOptions') handleToggleDropdownOptions: EventEmitter = new EventEmitter(); @Output('incorrectEvent') incorrectInput: EventEmitter = new EventEmitter(); @Output('blurInput') blurInput: EventEmitter = new EventEmitter(); @Output('focusInput') focusInputEvent: EventEmitter = new EventEmitter(); @Output('change') changeInput: EventEmitter = new EventEmitter(); @Output('commandEvent') commandEvent: EventEmitter = new EventEmitter(); @Output('clear') clearInputEvent: EventEmitter = new EventEmitter(); // Dropdown @Output('showHideDropdown') showHideDropdownEvent: EventEmitter = new EventEmitter(); @Output('dropDownKeyNavigation') dropDownKeyNavigationEvent: EventEmitter<{ keyCode: number; data: ICaInput | null; }> = new EventEmitter<{ keyCode: number; data: ICaInput | null; }>(); // variables public isFocusInput = false; public isTouchedInput = false; public isVisibleCommands = false; public isDropdownToggler = false; public isCapsLockOn = false; public isEditInput = false; // events public setCommandEvent = new EventInputManager( null, this.commandEvent ); public setClearInputEvent = new EventInputManager( false, this.clearInputEvent ); public setIncorrectInput = new EventInputManager( false, this.incorrectInput ); public setBlurInput = new EventInputManager(false, this.blurInput); public setChangeInput = new EventInputManager( null, this.changeInput ); public setShowHideDropdown = new EventInputManager( null, this.showHideDropdownEvent ); public setDropDownKeyNavigation = new EventInputManager<{ keyCode: number; data: ICaInput | null; }>(null, this.dropDownKeyNavigationEvent); // Password public isTogglePassword: boolean = false; // Date public newInputChanged: boolean = false; // Destroy private destroy$: Subject = new Subject(); public inputSvgRoutes = InputSvgRoutes; public priceSeperatorWithFilledValue = true; public inputCommandsType = InputCommandsType; public inputStringEnum = InputStringEnum; public dropdownTemplateTypeEnum = DropdownTemplateTypeEnum; constructor( @Self() public superControl: NgControl, public cdRefd: ChangeDetectorRef, public thsep: ThousandSeparatorPipe, public caInputValidationService: CaInputValidationService ) { super(cdRefd, thsep); this.superControl.valueAccessor = this; } get getSuperControl() { return this.superControl.control; } ngOnInit(): void { this.initChangesListener(); } ngAfterViewInit(): void { this.autoFocusFirstInput(); this.superControl?.valueChanges ?.pipe(takeUntil(this.destroy$)) .subscribe((value) => { this.transformText(value); }); } public initStateService(): void {} public outputListeners(): void {} public initChangesListener(): void { const combinedChanges = combineLatest([ this.getSuperControl?.valueChanges, this.getSuperControl?.statusChanges, ]); combinedChanges.pipe(takeUntil(this.destroy$)).subscribe(() => { this.cdRef.detectChanges(); }); } public writeValue(obj: InputChangeValue): void { if (this._inputConfig.priceSeparator) { if (obj && this.priceSeperatorWithFilledValue) this.input.nativeElement.value = this.thousandSeparatorPipe.transform(obj); else this.input.nativeElement.value = obj; this.priceSeperatorWithFilledValue = false; } this.writeValueBase(obj); } public registerOnChange(fn: any): void { this.onChange = fn; } public onChange(_: any): void {} public registerOnTouched(): void {} public onBlur(event?: FocusEvent): void { this.blurInput.emit(true); this.onBlurBase(event); } public onTogglePassword(event: Event): void { event.preventDefault(); this.isTogglePassword = !this.isTogglePassword; } public trackIdentity = (index: number): number => index; ngOnDestroy(): void { this.destroy$.next(); this.destroy$.complete(); } }