Search code examples
angularangular-reactive-formsphone-numberinput-field

Add plus sign "+" before input value in Angular2


The question sounds pretty easy, but I could found any clear solution for it.

I have custom input field (I'm using reactive forms approach) for phone numbers. The aim is to always have a plus sign before input value.

Requirements:

  • the entire input value including plus sign should be selectable (i.e. the hack with adding span-s or div-s with plus sign before input is not acceptable)
  • if the input value is empty - the plus sign can be removed, otherwise it should be added at the beginning of the input value if we add numbers
  • using third party libraries is not acceptable
  • when patching the form control with the new value (for example '123456') - it should also add plus sign before

How can we implement this logic in Angular2 project?


Solution

  • Here is a function that you could bind to the (change) event of your input:

    processInput(inputVal: string = null) {
        if (!inputVal) {
            inputVal = this.myForm.get('myInput').value; // since you're using reactive forms
        }
    
        if (inputVal === '') {
            // Do nothing
        } else if (inputVal.match(/^\d*$/)) {
            if (!inputVal.includes('+')) {
                inputVal = '+' + inputVal;
            }
        }
    
        // Then patch your 'myInput' value in your form with 'inputVal'
        this.myForm.patchValue({ 'myInput': inputVal });
    }
    
    safePatchMyInput(value: string) {
        this.processInput(value);
    }
    

    This implementation will add a plus sign if (and only if) the input string contains purely numbers. It also allows you to empty the input entirely (including the plus sign).

    Edit: The addition of the safePatchMyInput method will allow you to manually patch that input and still utilize the same input processing from the previous funciton. (This means adding the default parameter to the previous funciton)

    Binding to the (change) event on your input would simply look like this:

    <input (change)="processInput()"/>
    

    Edit 2

    Here is an updated solution that works with FormControl.registerOnChange to process the input even if it was set manually via patchValue.

    Angular Component:

    myForm: FormGroup;
    
    constructor() {
      this.myForm = new FormGroup({
        'myInput': new FormControl('')
      })
    }
    
    ngOnInit() {
      const myInput = this.myForm.get('myInput') as FormControl;
      myInput.registerOnChange(this.processInput);
    }
    
    processInput = () => {
      let inputVal = this.myForm.get('myInput').value;
    
      if (inputVal === '') {
        // Do nothing
      } else if (inputVal.match(/^\d*$/)) {
        if (!inputVal.includes('+')) {
          inputVal = '+' + inputVal;
    
          // Then patch your 'myInput' value in your form with 'inputVal'
          this.myForm.patchValue({ 'myInput': inputVal });
        }
      }
    }
    

    HTML Template:

    <form [formGroup]="myForm">
        <input formControlName="myInput" (input)="processInput()"/>
    </form>
    

    Stackblitz, for reference.