'How to force ngModel update when value did not change?
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();
}
}
Solution 1:[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
Solution 2:[2]
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.
Solution 3:[3]
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
}
Solution 4:[4]
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;
});
}
Solution 5:[5]
You can add else part to reflect changes.
public validate(value){
if(value>100)
this.value=100;
else
this.value = value
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Faisal |
| Solution 2 | Romain |
| Solution 3 | user1075296 |
| Solution 4 | federico scamuzzi |
| Solution 5 | asdf_enel_hak |
