我对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
答案 0 :(得分:1)
我真的认为有一种方法可以使用HostListener
指令停止此事件。
Angular在调用侦听器之前检测到此事件,因此停止传播不会影响您在父组件中作出反应的(没有证据证明我可能是错)ngModelChange
之类的Angular事件。
我建议提供指示值更改的自己的事件,并在您真正希望它发出时发出它:
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);
}
}
}
然后,您可以将ngModelChanged
绑定替换为numberChanged
:
<input type="text" [ngModel]="value" (numberChanged)="onChange($event)" numbersOnly/>
演示: https://stackblitz.com/edit/angular-numbers-only-directive-a2mv6e
答案 1 :(得分:0)
为了在反应形式中使用,我最终制作了一个实现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>