Phone mask directive in Angular 8

Viewed 1724

I have this phone mask directive which accepts a phone number in US format. However, when i clear the contents in the input by hitting backspace one by one, the value inside the input form is not being emptied. I didn't realize this issue until I logged the input value of the form.

And, when I clear the input form at once, it is being emptied. But, clearing by form value one by one hitting the backspace always leaves one value.

input-form-value

How do I clear the input value when the form value is empty?

I created a working example using StackBlitz. Could anyone please help?

Directive

export class PhoneMaskDirective {
  constructor(public ngControl: NgControl) {}

  @HostListener("ngModelChange", ["$event"])
  onModelChange(event) {
    this.onInputChange(event, false);
  }

  @HostListener("keydown.backspace", ["$event"])
  keydownBackspace(event) {
    this.onInputChange(event.target.value, true);
  }

  onInputChange(event, backspace) {
    if (event == null) {
      return "";
    }
    let newVal = event.replace(/\D/g, "");

    if (backspace && newVal.length <= 6) {
      newVal = newVal.substring(0, newVal.length - 1);
    }
    if (newVal.length === 0) {
      newVal = "";
    } else if (newVal.length <= 3) {
      newVal = newVal.replace(/^(\d{0,3})/, "($1)");
    } else if (newVal.length <= 6) {
      newVal = newVal.replace(/^(\d{0,3})(\d{0,3})/, "($1) $2");
    } else if (newVal.length <= 10) {
      newVal = newVal.replace(/^(\d{0,3})(\d{0,3})(\d{0,4})/, "($1) $2-$3");
    }
    this.ngControl.valueAccessor.writeValue(newVal);
  }
}

2 Answers

Recommended way is to use @HostBindings and @HostListeners instead of the host property

remove host and add @HostListener

@HostListener('ngModelChange', ['$event'])
  onModelChange(event) {
    this.onInputChange(event, false);
  }

  @HostListener('keydown.backspace', ['$event'])
  keydownBackspace(event) {
    this.onInputChange(event.target.value, true);
  }
Related