[英]Why does the oninput event behave differently in Angular than it does in JavaScript?
I'm learning Angular with TypeScript, and a few inconsistencies with JavaScript are troubling me.我正在学习 Angular 和 TypeScript,与 JavaScript 的一些不一致让我感到不安。 Here's a function which works perfectly with pure JavaScript (it programmatically sets
min
and max
attributes to an input - please don't ask me why I'd want to do that programmatically ):这是一个 function 与纯 JavaScript 完美配合(它以编程方式设置输入的
min
和max
属性 - 请不要问我为什么我想以编程方式这样做):
function change_number(input,min,max) { if(input.value > max) input.value = max; else if(input.value < min) input.value = min; }
<input type='number' oninput='change_number(this,1,5)' placeholder='Enter a number' />
In Angular and TypeScript, the function behaves strangely: If I enter 10
into the input field, it doesn't reset to 5
, until I enter another digit, meaning the value is only read after the input
event (and not on -input - don't know if that makes sense). In Angular and TypeScript, the function behaves strangely: If I enter
10
into the input field, it doesn't reset to 5
, until I enter another digit, meaning the value is only read after the input
event (and not on -input -不知道这是否有意义)。 What's more strange is it works fine with the keydown
and keyup
events.更奇怪的是它与
keydown
和keyup
事件配合得很好。 Why this behaviour?为什么会有这种行为? Is it linked to the way Angular binds events to inputs?
它是否与 Angular 将事件绑定到输入的方式相关联? I have a feeling understanding this would help me better understand Angular's binding mechanism with
NgModel
我有一种感觉,理解这将有助于我更好地理解 Angular 与
NgModel
的绑定机制
FYI, here's how I called the function in Angular (using the Ionic Framework) - I used the bound quantity
in [(ngModel)]
as the value of the input:仅供参考,这是我在 Angular 中调用 function 的方式(使用 Ionic 框架) - 我使用
[(ngModel)]
中的绑定quantity
作为输入值:
<ion-input type='number' (input)='change_numbers(1,5)' [(ngModel)]='quantity'></ion-input>
Angular framework is behaving perfectly the way it has to . Angular 框架表现得非常完美。 It is us who are a bit confused.
是我们有点糊涂。
Angular handles forms in a bit different manner. Angular 处理 forms 的方式略有不同。 There are two approaches to build forms in angular -
有两种方法可以在 angular 中构建 forms -
The Key difference between them is the above Sync/async behaviour .它们之间的主要区别在于上述Sync/async 行为。 In simple terms we can say that.
简单来说,我们可以这么说。
x X
<ion-input type='number' (input)='change_numbers(1,5)' [(ngModel)]='quantity'></ion-input>
Above one is a Template-driven approach.以上是一种模板驱动的方法。 Here we are using
[(ngModel)]
, this updates only after the data has changed.这里我们使用
[(ngModel)]
,仅在数据更改后才会更新。
In order to make a reactive input field, use below code:-为了制作反应输入字段,请使用以下代码:-
in app.component.ts file在 app.component.ts 文件中
import { Component } from '@angular/core';
import { FormBuilder, FormGroup } from '@angular/forms';
import { debounceTime, distinctUntilChanged } from 'rxjs/operators';
@Component({
selector: 'dd-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
export class AppComponent {
form: FormGroup;
min = 0;
max = 5;
constructor(private fb: FormBuilder) {
this.buildForm();
}
buildForm(): void {
this.form = this.fb.group({
numberInput: ''
});
this.form.get('numberInput').valueChanges.pipe(distinctUntilChanged()).subscribe(_ => {
if (_) {
if (_ > this.max) {
this.form.get('numberInput').setValue(5);
}
if (_ < this.min) {
this.form.get('numberInput').setValue(0);
}
} else {
this.form.get('numberInput').reset('');
}
});
}
}
In app.html (Here i am posting 2 way to express it.)在 app.html 中(这里我发布了 2 种表达方式。)
<form [formGroup]="form">
<!-- <input type='number' [min]='0' [max]='5' formControlName="numberInput" /> we can also this one, more easy just set value dynamically -->
<input type='number' formControlName="numberInput" />
</form>
NOTE:- DONT FORGET TO IMPORT ReactiveFormsModule注意:- 不要忘记导入ReactiveFormsModule
More about forms can found in the official docs: -https://angular.io/guide/forms-overview更多关于 forms 的信息可以在官方文档中找到:-https://angular.io/guide/forms-overview
To understand why it behaves like that, first you need to be familiar with two basic concepts:要理解它为什么会这样,首先你需要熟悉两个基本概念:
[(ngModel)]="quantity"
is nothing more than sugar syntax which is translated to [ngModel]="quantity" (ngModelChange)="quantity = $event"
[(ngModel)]="quantity"
只不过是被翻译成[ngModel]="quantity" (ngModelChange)="quantity = $event"
的糖语法 With this knowledge, you can understand what really happens here:有了这些知识,您就可以了解这里真正发生了什么:
onNgModelChange
is triggered, quantity
is set to 4
. onNgModelChange
被触发, quantity
设置为4
。 The inner model value of input
(more specifically, ngModel
directive) is still equal to undefined
. input
的内部model值(更具体地说, ngModel
指令)仍然等于undefined
。change_numbers
is called, quantity
is not changed. change_numbers
被调用, quantity
不变。ngModelChange
and change_numbers
all called in a single callstack due to how angular handles events).ngModelChange
和change_numbers
都在单个调用堆栈中调用)。 Change detection is performed.quantity
( 4
now) is bound to the ngModel
( undefined
now), angular detects a need to update the UI (because undefined != 4
of course).quantity
(现在4
)绑定到ngModel
(现在undefined
),所以 angular 检测到需要更新 UI(因为undefined != 4
当然)。8
.8
。onNgModelChange
is triggered, quantity
is set to 48
. onNgModelChange
被触发, quantity
设置为48
。 The inner model value of input
(more specifically, ngModel
directive) is still equal to 4
. input
(更具体地说, ngModel
指令)的内部model值仍然等于4
。change_numbers
is called, quantity
is changed to 5
. change_numbers
, quantity
更改为5
。quantity
( 5
now) is bound to the ngModel
( 4
now), angular detects a need to update the UI (because 5 != 4
of course).quantity
(现在5
)绑定到ngModel
(现在4
),所以 angular 检测到需要更新 UI(因为5 != 4
当然)。7
.7
。onNgModelChange
is triggered, quantity
is set to 57
. onNgModelChange
被触发, quantity
设置为57
。 The inner model value of input
(more specifically, ngModel
directive) is still equal to 5
. input
(更具体地说, ngModel
指令)的内部model值仍然等于5
。change_numbers
is called, quantity
is changed to 5
. change_numbers
, quantity
更改为5
。quantity
( 5
now) is bound to the ngModel
(also 5
now), angular doesn't detect a need to update the UI (because 5 == 5
of course).quantity
(现在5
)绑定到ngModel
(现在也是5
),所以 angular 没有检测到需要更新 UI(因为5 == 5
当然)。 A solution to that might be calling detectChanges
in onNgModelChange
method.一个解决方案可能是在
onNgModelChange
方法中调用detectChanges
。 It will work, because in this moment we will update the inner model
value of ngModel
(even if it is much higher than 5
).它会起作用,因为此时我们将更新
ngModel
的内部model
值(即使它远高于5
)。 So even if we next decrease the value to 5
, angular still will detect a need to update the UI.因此,即使我们接下来将值减小到
5
,angular 仍然会检测到需要更新 UI。
I hope that explains everything.我希望这能解释一切。 If you'll have some questions, don't hesitate to let me know.
如果您有一些问题,请随时告诉我。 Cheers!
干杯!
Try this out, this works well, let me know if this is not what you want to achieve试试这个,效果很好,如果这不是你想要实现的,请告诉我
html html
<input type='number' (change)='change_numbers(1,5)' [(ngModel)]="quantity">
javascript javascript
change_numbers(min,max) {
if(this.quantity > max)
this.quantity = max;
else if(this.quantity < min)
this.quantity= min;
}
Not sure if this helps, but I found these;不确定这是否有帮助,但我找到了这些;
how to use oninput in Angular? 如何在 Angular 中使用 oninput?
oninput not working in Angular. oninput 在 Angular 中不起作用。 Alternative?
选择?
They seem to talk a lot about using (input)
;他们似乎经常谈论使用
(input)
; if you've tried it?如果你尝试过?
Reading on google about this issue, it just seems like if you're using Angular you have to do things " The Angular Way " or oddities like what you're trying to seek an answer for occur.在谷歌上阅读有关此问题的信息,似乎如果您使用的是 Angular,您必须执行“ Angular 方式”或奇怪的事情,例如您试图寻找答案的事情。
As Kuiil from The Mandolorian says;正如 Mandolorian 的 Kuiil 所说; "This is the way"
“就是这样”
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.