输入字段只接受数字而不在输入其他字符时触发事件
Input field accepting only numbers without firing events when input other caracters
我对 html 数字输入的默认行为不满意,我想要一个只接受数字的简单输入。
我创建了这个指令:
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();
}
}
}
我面临的问题是 "event.stopPropagation()" 不会停止事件传播,即使从用户的角度来看输入值没有改变,也会触发事件。
如何在字段值未更改时停止事件传播?
编辑:
为了更好地理解,这里有一个 stackblitz 示例:
https://stackblitz.com/edit/angular-numbers-only-directive
我真的不认为有什么方法可以使用带有 HostListener
的指令来停止此事件。
Angular 在调用侦听器之前检测到此事件,因此停止传播不会影响 Angular 事件,例如您在父组件中做出反应的 ngModelChange
。(没有证据证明我可能是错的)
我建议提供自己的事件指示值更改,并在您真正希望它发出时发出它:
export class NumberDirective {
@Output() numberChanged = new EventEmitter<number>();
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) {
this.numberChanged.emit(initalValue);
}
}
}
然后你可以用numberChanged
替换ngModelChanged
绑定:
<input type="text" [ngModel]="value" (numberChanged)="onChange($event)" numbersOnly/>
演示:
https://stackblitz.com/edit/angular-numbers-only-directive-a2mv6e
为了在响应式表单中使用,我最终制作了一个实现 ControlValueAccessor
的自定义组件:
组件声明(摘录):
@Component({
selector: 'number',
template: `
<input type="text" [(ngModel)]="value" numbersOnly/>
`,
...
]
})
export class NumberInputComponent implements ControlValueAccessor {
...
set value(value) {
const tmp = value.replace(/[^0-9]*/g, '');
if(tmp && tmp !== '' && +tmp !== +this._value) {
this._value = +tmp;
this.onChange(this._value);
}
}
...
}
用法:
<number [formControl]="formControl"></number>
我对 html 数字输入的默认行为不满意,我想要一个只接受数字的简单输入。
我创建了这个指令:
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();
}
}
}
我面临的问题是 "event.stopPropagation()" 不会停止事件传播,即使从用户的角度来看输入值没有改变,也会触发事件。
如何在字段值未更改时停止事件传播?
编辑: 为了更好地理解,这里有一个 stackblitz 示例: https://stackblitz.com/edit/angular-numbers-only-directive
我真的不认为有什么方法可以使用带有 HostListener
的指令来停止此事件。
Angular 在调用侦听器之前检测到此事件,因此停止传播不会影响 Angular 事件,例如您在父组件中做出反应的 (没有证据证明我可能是错的)ngModelChange
。
我建议提供自己的事件指示值更改,并在您真正希望它发出时发出它:
export class NumberDirective {
@Output() numberChanged = new EventEmitter<number>();
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) {
this.numberChanged.emit(initalValue);
}
}
}
然后你可以用numberChanged
替换ngModelChanged
绑定:
<input type="text" [ngModel]="value" (numberChanged)="onChange($event)" numbersOnly/>
演示: https://stackblitz.com/edit/angular-numbers-only-directive-a2mv6e
为了在响应式表单中使用,我最终制作了一个实现 ControlValueAccessor
的自定义组件:
组件声明(摘录):
@Component({
selector: 'number',
template: `
<input type="text" [(ngModel)]="value" numbersOnly/>
`,
...
]
})
export class NumberInputComponent implements ControlValueAccessor {
...
set value(value) {
const tmp = value.replace(/[^0-9]*/g, '');
if(tmp && tmp !== '' && +tmp !== +this._value) {
this._value = +tmp;
this.onChange(this._value);
}
}
...
}
用法:
<number [formControl]="formControl"></number>