Eugene Sukh
Eugene Sukh

Reputation: 2727

Make only two decimal after point (Angular)

I have a directive for text input, that replaces text symbols and allows to type decimal numbers only.

Here is code for this directive

import { NgControl } from '@angular/forms';
import { HostListener, Directive } from '@angular/core';

@Directive({
    exportAs: 'decimal-number-directive',
    selector: 'decimal-number-directive, [decimal-number-directive]'
})
export class DecimalNumberDirective {
    private el: NgControl;
    constructor(ngControl: NgControl) {
        this.el = ngControl;
    }
    // Listen for the input event to also handle copy and paste.
    @HostListener('input', ['$event.target.value'])
    onInput(value: string) {
        // Use NgControl patchValue to prevent the issue on validation
        this.el.control.patchValue(value.replace(/[^0-9].[^0-9]/, ''));
    }
}

Now I can write n - number decimal symbols. I need only two. How I can do this?

Upvotes: 0

Views: 4791

Answers (2)

The fourth bird
The fourth bird

Reputation: 163632

In your pattern [^0-9].[^0-9] you are replacing 3 characters with an empty string. You match not a digit, any char except a newline using a dot and again not a digit using a negated character class [^

If you want to remove all chars except digits and dots you are still not sure if the format is correct because ... could then also be valid.

Instead of replace, try matching a value with 2 decimals after the dot.

^[0-9]+\.[0-9]{2}$

If you would allow starting with a dot, you could use a * instead of +:

^[0-9]*\.[0-9]{2}$

Example using test:

let pattern = /^[0-9]+\.[0-9]{2}$/;
["2.22", "....", "1", "3.299"].forEach(s => console.log(s + ": " + pattern.test(s)));

Or using match:

let pattern = /^[0-9]+\.[0-9]{2}$/;
["2.22", "....", "1", "3.299"].forEach(s => {
  let res = s.match(pattern);
  console.log((null === res ? "No match: " : "Match: ") + s)
});

Upvotes: 0

Eugene Sukh
Eugene Sukh

Reputation: 2727

So to show decimal places and not allow symbols I need to write directive like this

    import { NgControl } from '@angular/forms';
import { HostListener, Directive, ElementRef } from '@angular/core';

@Directive({
    exportAs: 'decimal-number-directive',
    selector: 'decimal-number-directive, [decimal-number-directive]',
})
export class DecimalNumberDirective {
    private regex: RegExp = new RegExp(/^\d*\.?\d{0,2}$/g);
    private specialKeys: Array<string> = ['Backspace', 'Tab', 'End', 'Home', '-'];
    constructor(private el: ElementRef) {}
    @HostListener('keydown', ['$event'])
    onKeyDown(event: KeyboardEvent) {
        console.log(this.el.nativeElement.value);
        // Allow Backspace, tab, end, and home keys
        if (this.specialKeys.indexOf(event.key) !== -1) {
            return;
        }
        let current: string = this.el.nativeElement.value;
        let next: string = current.concat(event.key);
        if (next && !String(next).match(this.regex)) {
            event.preventDefault();
        }
    }
}

Upvotes: 3

Related Questions