Skip to content

Instantly share code, notes, and snippets.

@dyazincahya
Created March 26, 2025 08:27
Show Gist options
  • Save dyazincahya/be7534ba793f6ab26547125ffc728b4c to your computer and use it in GitHub Desktop.
Save dyazincahya/be7534ba793f6ab26547125ffc728b4c to your computer and use it in GitHub Desktop.
Time Mask Input Directive for Angular
import { Directive, ElementRef, HostListener, forwardRef } from '@angular/core';
import { NG_VALUE_ACCESSOR, ControlValueAccessor } from '@angular/forms';
@Directive({
selector: '[timeMask]',
providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => timeMaskDirective),
multi: true,
},
],
})
export class TimeMaskDirective implements ControlValueAccessor {
private onChange: (value: string) => void;
private onTouched: () => void;
constructor(private el: ElementRef) {}
@HostListener('input', ['$event'])
onInput(event: Event) {
const input = this.el.nativeElement;
let value = input.value.replace(/\D/g, ''); // Hanya angka
if (value.length > 4) {
value = value.substring(0, 4);
}
if (value.length >= 3) {
value = `${value.substring(0, 2)}:${value.substring(2)}`;
}
input.value = value;
if (this.onChange) {
this.onChange(value);
}
}
@HostListener('blur', ['$event'])
onBlur(event: FocusEvent) {
const input = this.el.nativeElement;
let value = input.value;
if (value.length === 2 && /^\d{2}$/.test(value)) {
value = `${value}:00`;
}
const parts = value.split(':');
if (parts.length === 2) {
let hours = parseInt(parts[0], 10);
let minutes = parseInt(parts[1], 10);
if (isNaN(hours) || hours < 0 || hours > 23) {
hours = 0;
}
if (isNaN(minutes) || minutes < 0 || minutes > 59) {
minutes = 0;
}
input.value = `${this.padZero(hours)}:${this.padZero(minutes)}`;
if (this.onChange) {
this.onChange(input.value);
}
}
if (this.onTouched) {
this.onTouched();
}
}
writeValue(value: string): void {
this.el.nativeElement.value = value;
}
registerOnChange(fn: any): void {
this.onChange = fn;
}
registerOnTouched(fn: any): void {
this.onTouched = fn;
}
private padZero(value: number): string {
return value < 10 ? `0${value}` : `${value}`;
}
}
@dyazincahya
Copy link
Author

Directive

timeMask

Features

  • The time format only supports HH:mm (hours and minutes).
  • Users only need to input the hour and minute numbers, and the colon (:) separator will be added automatically.
  • If the user enters only two digits for the hour, the minutes will automatically be set to 00.

How to Implementation?

Load the Directive

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule } from '@angular/forms';
import { TimeMaskDirective } from './time-mask.directive'; // Adjust the path according to your directive location.

@NgModule({
  declarations: [
    AppComponent,
    TimeMaskDirective // Make sure the directive is included here
  ],
  imports: [
    BrowserModule,
    FormsModule,
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

Using the Directive

<input type="text" timeMask placeholder="HH:mm" />

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment