Why I can not limit an input's value length with Angular NgModel?

Issue

I have an input field with two way binding and I want to change the user input to uppercase and limit it to 3 characters. I’m doing this in the setter of the variable. The uppercase replacement works if I try to do a substring it does not update the field value anymore, the property is correctly updated though.

If I enter “abc” it replaces it correctly to “ABC” but as soon as I type more than 3 characters, the other characters are not removed. For example “abcde” displays “ABCde” in the input.
Please see the stackblitz example: https://stackblitz.com/edit/angular-bpuh8a

<input type="text" id="airport" name="airport" [(ngModel)]="airport">
private _airport = '';
get airport(): string {
  return this._airport;
}
set airport(value: string) {
  this._airport = value.substring(0, 3).toUpperCase();
}

I know that I can limit the field length using maxlength and it works but I want to understand why what I’m doing here is not working.

I’ve tried calling a method in ngModelChange as well but the result is the same

Thank you for your help.

Solution

First you need to understand the viewModel and model.

When you type the fourth character, model still is ABC, so Angular doesn’t update the viewModel (Source code), but the input element will still respond to your typing.

The solution to this problem is to manually control the input element value. or set maxLength.

<label for="airport">Airport </label>
<input #input type="text" id="airport" name="airport" [ngModel]="airport" (ngModelChange)="onChange($event)">
{{ airport }}
import { Component, ViewChild, ElementRef } from '@angular/core';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
})
export class AppComponent  {

  @ViewChild('input', { static: false }) input: ElementRef<HTMLInputElement>;
  airport = '';

  onChange(value: string) {
     this.airport = value.substring(0, 3).toUpperCase();
     this.input.nativeElement.value = this.airport;
  }
}

https://stackblitz.com/edit/angular-nwwjs7?file=src/app/app.component.ts

Answered By – Hsuan Lee

Answer Checked By – Pedro (AngularFixing Volunteer)

Leave a Reply

Your email address will not be published.