import { CommonModule } from '@angular/common'; import { Component, Input, forwardRef, OnInit, OnDestroy } from '@angular/core'; import { ControlValueAccessor, NG_VALUE_ACCESSOR,ReactiveFormsModule, FormControl, Validators } from '@angular/forms'; import { Subject, takeUntil } from 'rxjs'; @Component({ selector: 'time-input', imports:[ReactiveFormsModule,CommonModule], template: ` `, providers: [ { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => TimeInputComponent), multi: true, }, ], }) export class TimeInputComponent implements ControlValueAccessor, OnInit, OnDestroy { @Input() placeholder: string = 'HH:MM'; @Input() initialValue: string = ''; // Added initialValue input @Input() disabled: boolean = false; timeControl = new FormControl('', [ Validators.pattern(/^([0-2][0-9]:[0-5][0-9])?$/), // Added more precise regex ]); private destroy$ = new Subject(); private _value: string = ''; private onChange: (value: string) => void = () => {}; private onTouched: () => void = () => {}; constructor() {} ngOnInit(): void { this.timeControl.valueChanges.pipe(takeUntil(this.destroy$)).subscribe((value) => { this.onChange(value || ''); // Pass the value to the parent form }); if (this.initialValue) { this.writeValue(this.initialValue); } this.timeControl.disable(); if(!this.disabled){ this.timeControl.enable(); } } ngOnDestroy(): void { this.destroy$.next(); this.destroy$.complete(); } get value(): string { return this._value; } set value(val: string) { this._value = val; this.onChange(val); this.onTouched(); } writeValue(value: string): void { this._value = value || ''; this.formatInput(this._value); // Use the formatting function } registerOnChange(fn: (value: string) => void): void { this.onChange = fn; } registerOnTouched(fn: () => void): void { this.onTouched = fn; } setDisabledState(isDisabled: boolean): void { this.disabled = isDisabled; if (isDisabled) { this.timeControl.disable(); } else { this.timeControl.enable(); } } onInput(event: Event): void { let input = (event.target as HTMLInputElement).value; input = input.replace(/[^0-9]/g, ''); // Remove non-numeric characters. if (input.length > 4) { input = input.slice(0, 4); // Limit to 4 digits } let formatted = ''; if (input.length > 2) { formatted = input.slice(0, 2) + ':' + input.slice(2); } else { formatted = input; } this.timeControl.setValue(formatted, { emitEvent: false }); // Prevent infinite loop this.value = formatted; } onBlur(): void { this.onTouched(); if (this.timeControl.valid) { return; } if (this.timeControl.value?.length === 0) { this.timeControl.setValue('', {emitEvent: false}); this.value = ''; return } this.formatInput(this.timeControl.value); } private formatInput(val: string | null): void { if (!val) { this.timeControl.setValue('', {emitEvent: false}); this.value = ''; return; } let numbersOnly = val.replace(/[^0-9]/g, ''); let formatted = ''; if (numbersOnly.length > 2) { formatted = numbersOnly.slice(0, 2) + ':' + numbersOnly.slice(2, 4); } else { formatted = numbersOnly; } if (formatted.length === 5 && this.timeControl.valid) { this.timeControl.setValue(formatted, {emitEvent: false}); this.value = formatted; } else if (numbersOnly.length <= 2) { this.timeControl.setValue(formatted, {emitEvent: false}); this.value = formatted; } else { this.timeControl.setValue('00:00', {emitEvent: false}); this.value = '00:00' } } }