4

I want to limit number input to 0-100 range, but on input, not during validation. I'm using ngModel to bind value and emitt change event:

<input [ngModel]="value" (ngModelChange)="validate($event)" />

And then check if value exceeds given limits:

public validate(value) {
    if (value > 100)
        this.value = 100;
    if (value < 0)
        this.value = 0;
}

And this partialy works. However if I say try to input 150 and value will switch to 100, I can then input anything over 100, because model value remains 100, and so input value is not updated. Is there any way to manually force this update?

EDIT: I missed quite important bit here. This behaviour seems to only occur to input with type=number. Text input wont exceed 100. My workaround is as Faisal suggested using keypress event with preventDefault like so:

public keyPress(event) {
    let inputChar: number = +String.fromCharCode(event.charCode);
    if (this.value + inputChar > 100 || this.value + inputChar < 0) {
        // Exceeded limits, prevent input
        event.preventDefault();
    }
}
K. Kowalczyk
  • 967
  • 13
  • 34

5 Answers5

4

I had the same problem and found a different solution that I liked more. As you said the problem is that the value in the model is the same before and after your function. What I did was to call Angular's change detection before I change the value so it registers a change. For this use the ChangeDetectorRef class and call its detectChanges method.

Thus, your function becomes :

public validate(value) {
    this.changeDetector.detectChanges();
    if (value > 100)
        this.value = 100;
    if (value < 0)
        this.value = 0;
}

And it works perfectly. Hope it helps.

Romain
  • 41
  • 2
  • Thank you@Romain. Way better than the selected solution that disables all arrow key and back space. With your solution, I managed to build a really nice formatted input. – Thierry D. Nov 28 '19 at 16:13
  • Thank you so much! Had the same problem with a checkbox, trying to change the value of the checkbox inside change method. Saved me 3 hours of searching! – amicoderozer Jan 19 '22 at 16:33
1

Use a regular expression to limit the user input.

Here is the html code for your input:

<input [(ngModel)]="value" 
       (keypress)="keyPress($event)"
       (ngModelChange)="validate($event)"  
        maxlength=3 />

.. and typescript code:

keyPress(event: any) {
    const pattern = /[0-9]/;
    let inputChar = String.fromCharCode(event.charCode);

    if (!pattern.test(inputChar)) {
        // invalid character, prevent input
        event.preventDefault();
    }
}

validate(value:number) {
    if(value>100) {
        this.value=100;
    }
}

Here is a working plunker: Plunker DEMO

FAISAL
  • 33,618
  • 10
  • 97
  • 105
  • This does not work for input type number, however if I check on key press if model value+input char exceeds 100 it seems to be patching what I had. Not really clean solution, but works. thanks. – K. Kowalczyk Aug 09 '17 at 06:38
1

I had a similar problem. My input does not update, when the result equals to the previous entry value.

I use @ViewChild like that : In your template :

<input #input [ngModel]="value" (ngModelChange)="validate($event)" />

In your TS file :

@ViewChild('input') input: ElementRef;

public validate(value) {
    if (value > 100)
        this.value = 100;
    if (value < 0)
        this.value = 0;
    this.input.writeValue(this.value); // force to update
}
user1075296
  • 581
  • 3
  • 10
0

another way .. as i Know is to use NgZone (equivalent of AngularJs $scope.$apply()) .. like:

constructor(private _ngZone:NgZone){

}


public validate(value){
    if(value>100)
        this.value=100;
    if(value<0)
        this.value=0;

this._ngzone.run(()=>{
 this.value=(value>100) ? 100  ? (value<0) ? 0 : 0;
});

}
federico scamuzzi
  • 3,708
  • 1
  • 17
  • 24
-1

You can add else part to reflect changes.

public validate(value){
    if(value>100)
        this.value=100;
    else
        this.value = value    
}
asdf_enel_hak
  • 7,474
  • 5
  • 42
  • 84
  • model value is correct, but since it did not change(if model value was 100, and I input 1000, it remains 100) input field is not updated to reflect this model. – K. Kowalczyk Aug 09 '17 at 06:14