Angular Input Directive for Decimal Numbers with Local Decimal Separator Handling

45 Views Asked by At

I am working on an Angular project where I need to create a custom directive for input fields that handle decimal numbers. The challenge I'm facing is ensuring compatibility with local decimal separators.

The directive should meet the following requirements:

  1. Accept decimal numbers with or without a leading zero, e.g., "0.123" or ".456".
  2. Automatically adjust to the user's local decimal separator (, or .).
  3. Restriction for negative numbers.
  4. Restrict non-numeric and non-decimal characters.
<input type="text" decimalNumbersOnly>
1

There are 1 best solutions below

0
Jakob On

@Directive({
  selector: 'input[decimalNumbersOnly]',
})
export class NumberDirectiveDecimal {
  private whatDecimalSeparator() {
    const n: number = 1.1;
    const locale =  window.navigator.language;
    const sel: string = n.toLocaleString(locale).substring(1, 2);
    return sel;
  }

  decimalSeparator: string = '';

  constructor(private _el: ElementRef) {
    this.decimalSeparator = this.whatDecimalSeparator();
  }

  @HostListener('input', ['$event']) onInputChange(event: any) {

    const initialValue = this._el.nativeElement.value;
    const regexPattern = new RegExp(`[^0-9\\${this.decimalSeparator}]`, 'g');
    this._el.nativeElement.value = initialValue.replace(regexPattern, '');

    const dotCount = (
      this._el.nativeElement.value.match(
        new RegExp(`\\${this.decimalSeparator}`, 'g')
      ) || []
    ).length;
    if (dotCount > 1) {
      this._el.nativeElement.value = this._el.nativeElement.value.slice(0, -1); // Remove the last dot if there are multiple dots
    }

    if (initialValue !== this._el.nativeElement.value) {
      event.stopPropagation(); // Stop the event propagation if the input value is changed
    }
  }
}