【问题标题】:Input field accepting only numbers without firing events when input other caracters输入其他字符时,输入字段仅接受数字而不触发事件
【发布时间】:2018-05-13 07:51:42
【问题描述】:

我对 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

【问题讨论】:

  • 这可能是问题所在。 “您可以使用 Event.cancelable 来检查事件是否可取消。为不可取消的事件调用 preventDefault() 无效。” developer.mozilla.org/en-US/docs/Web/API/Event/preventDefault
  • 我已经检查了您的示例,您从指令中捕获的事件是不可取消的。因此,它照常传播。
  • 感谢您的回答,您有什么建议可以以干净的方式实现最初的目标吗?非常感谢您对 stackblitz 代码进行编辑。
  • 尝试使用 HostListener 'keyDown',而不是 HostListener 'input'
  • @Eliseo 事件仍会使用keydown 触发。

标签: angular typescript angular-directive


【解决方案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);
    }
  }

}

然后你可以用numberChanged替换ngModelChanged绑定:

<input type="text" [ngModel]="value" (numberChanged)="onChange($event)" numbersOnly/>

演示: https://stackblitz.com/edit/angular-numbers-only-directive-a2mv6e

【讨论】:

  • 感谢您的建议,因为我在表单上使用了一些字段,并听取了表单值的更改,这将为数字字段提供不同的情况。我一拿到电脑就试一试。
  • 我得到了两种情况的解决方案,赏金会尽快发放。感谢您的帮助。
【解决方案2】:

为了在响应式表单中使用,我最终制作了一个自定义组件来实现 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>

Here is the stackblitz.

【讨论】:

    猜你喜欢
    • 2017-05-18
    • 1970-01-01
    • 2021-09-05
    • 1970-01-01
    • 1970-01-01
    • 2019-07-20
    • 1970-01-01
    • 1970-01-01
    • 2022-11-25
    相关资源
    最近更新 更多