Angular 将表单值修改为用户类型

Angular 将表单值修改为用户类型,angular,Angular,我正在尝试在用户键入时修改输入值。考虑这个简化的例子: app.component.html <label for="testInput">Enter Text Here: </label> <input id="testInput" type="text" [ngModel]="inputVal" (ngModelChange)="handleChange($event)" > 控制台日志清楚地显示handleChange正在运行,并删除非

我正在尝试在用户键入时修改输入值。考虑这个简化的例子:

app.component.html

<label for="testInput">Enter Text Here: </label>
<input
  id="testInput"
  type="text"
  [ngModel]="inputVal"
  (ngModelChange)="handleChange($event)"
>
控制台日志清楚地显示
handleChange
正在运行,并删除非数字。但是,表单值并不反映这一点。例如,如果要键入“123abc”,则表单值将仅显示该值。控制台日志将显示“1”,然后是“12”,然后是“123”四次


从很多人的反应来看,这很奇怪。这里发生了什么?

您的问题是更改检测,如果键入“1a2b3c”,您将在页面上看到以下内容:

一, 1a 12 12b 123 123c

这是因为如果输入以字母结尾,
inputVal
不会改变

一种可能的解决方案是触发更改检测。这可以通过以下方式完成:

从'@angular/core'导入{Component,ChangeDetectorRef};
@组成部分({
选择器:'应用程序根',
templateUrl:“./app.component.html”,
样式URL:['./app.component.css']
})
导出类AppComponent{
inputVal:string='';
构造函数(私有cdr:ChangeDetectorRef){}
handleChange(纽瓦尔){
让justDigits=newVal.replace(/[^0-9]/g');
log('仅包含数字的新值:',justDigits);
this.inputVal=null;//更改模型并触发更改检测
this.cdr.detectChanges();
this.inputVal=justDigits;//再次更改它,并让更改检测发生
}
}

Stackblitz:

对于这种情况,最好使用
管道。在您的情况下,您可以使用
管道
,它将过滤除数字以外的所有内容

这里的NumberDirective只允许数字

import { Directive, ElementRef, HostListener, Input } from '@angular/core';
import { NgControl } from '@angular/forms';

@Directive({
  selector: 'input[numbersOnly]'
})
export class NumberDirective {

  constructor(private _el: ElementRef) { }

  @HostListener('input', ['$event']) onInputChange(event) {
    const initalValue = this._el.nativeElement.value;
    this._el.nativeElement.value = initalValue.replace(/[^0-9]*/g, '');
    if (initalValue !== this._el.nativeElement.value) {
      event.stopPropagation();
    }
  }

}

以下是工作演示-

您需要了解
ngModelChange
的工作原理。每次输入更改时,都会调用
ngModelChange
。如果键入1,将调用
ngModelChange
。然后,当您下次键入2时,再次调用
ngModelChange
。每次输入都在更改,因此
console.log
会打印1、12、123123、123、123(最后3次123是由于
replace()
)。这就是angular的工作原理和ngModelChange的工作原理。我建议您使用
(keyup)
事件,而不是
(ngModelChange)
@crueEngine。令人惊讶的是,控制台日志中没有显示。正如我所预料的那样。令人惊讶的是,设置inputVal并没有改变显示给用户的输入。但我更感兴趣的是找出为什么这不起作用……这也不起作用,价值没有达到模型:
import { Directive, ElementRef, HostListener, Input } from '@angular/core';
import { NgControl } from '@angular/forms';

@Directive({
  selector: 'input[numbersOnly]'
})
export class NumberDirective {

  constructor(private _el: ElementRef) { }

  @HostListener('input', ['$event']) onInputChange(event) {
    const initalValue = this._el.nativeElement.value;
    this._el.nativeElement.value = initalValue.replace(/[^0-9]*/g, '');
    if (initalValue !== this._el.nativeElement.value) {
      event.stopPropagation();
    }
  }

}