Javascript Angular 6 event.stopPropagation()不在指令中工作(模板驱动的表单已获取event.data)

Javascript Angular 6 event.stopPropagation()不在指令中工作(模板驱动的表单已获取event.data),javascript,angular,html,typescript,Javascript,Angular,Html,Typescript,我正在尝试制作一个用于表单的citizenNumber组件。它实现了ngModel的ControlValueAccessor 导出类CitizenNumberComponent实现ControlValueAccessor{ 私有_值:字符串; @Input()占位符=“”; @Input()required=true; 获取值():字符串{ 返回此值; } 设置值(值:字符串){ 此值为._值=值; 这是一个变化(值); } //进行更改时将触发的寄存器“fn” //这就是我们将更改发送回表单的

我正在尝试制作一个用于表单的citizenNumber组件。它实现了ngModel的ControlValueAccessor

导出类CitizenNumberComponent实现ControlValueAccessor{
私有_值:字符串;
@Input()占位符=“”;
@Input()required=true;
获取值():字符串{
返回此值;
}
设置值(值:字符串){
此值为._值=值;
这是一个变化(值);
}
//进行更改时将触发的寄存器“fn”
//这就是我们将更改发送回表单的方式
注册变更(fn:任何):无效{
这一变化=fn;
}
//未使用,用于触摸输入
注册表(fn:any):void{}
//这是为组件设置的初始值
writeValue(值:字符串):无效{
如果(值){
此值为._值=值;
}
}
//registerOnChange中设置的将更改发送回表单的方法
传播变化=((uu0:any)=>{};
}
我做了一个数字指令来限制输入,除了0-9位

在numberDirective中,我使用了“输入”事件,因为按键、向下键和向上键在android chrome中不起作用

@Directive({
    selector: 'input[jhiNumbersOnly]'
})
export class NumberDirective {
    private specialKeys: Array<string> = ['Backspace', 'Delete', 'Insert', 'Tab', 'End', 'Home', 'ArrowRight', 'ArrowLeft'];

    @HostListener('input', ['$event']) onInput(event) {
        const key = event['data'];
        // Allow Backspace, tab, end, and home keys
        if (this.specialKeys.indexOf(key) !== -1) {
            return;
        }
        const initalValue = event.target['value'];
        event.target['value'] = initalValue.replace(/[^0-9]*/g, '');
        if (initalValue !== event.target['value']) {
            event.stopPropagation();
        }
    }
}
@指令({
选择器:“输入[jhiNumbersOnly]”
})
导出类编号指示{
private specialKeys:Array=[“退格”、“删除”、“插入”、“制表”、“结束”、“主页”、“箭头右”、“箭头左”];
@HostListener('input',['$event'])onInput(event){
常量键=事件['data'];
//允许使用退格键、制表符键、结束键和主控键
if(此.specialKeys.indexOf(键)!=-1){
返回;
}
常量initalValue=event.target['value'];
event.target['value']=initalValue.replace(/[^0-9]*/g');
if(initalValue!==event.target['value']){
event.stopPropagation();
}
}
}
最后,一切正常,但尽管事件已停止,模型仍将获取值。

例如,我的输入maxlength为11。输入10个数字后,如果输入了某些键(0-9除外),则表单将被验证

查看组件


你能帮我解决我的问题吗?

你应该用
键控处理程序替换
输入处理程序。然后,如果钥匙是好的,什么也不做,否则,阻止事件发生

问题是,如果您收听输入事件,则为时已晚,
ngModel
将被更新,因此您必须收听
keydown
事件并对其进行适当过滤

@HostListener('keydown', ['$event']) onKeyDown(e: KeyboardEvent) {
  if (this.specialKeys.indexOf(e.key) !== -1 || new RegExp(/[0-9]/g).test(e.key)) {
      return;
  }
  e.preventDefault();
}
我在你的stackblitz演示中测试了这段代码,效果很好

编辑:您提到您不能使用按键处理程序,对不起

我设法让它与
元素上的
oninput
处理程序一起工作,并删除了您对输入的指令:

<div class = "form-group">
  <label class = "form-control-label label-color" for = "citizenNumber">Citizen Number
  </label>
  <input type = "text" 
          class = "form-control input-css" 
          name = "citizenNumber"
          id = "citizenNumber"
          #citizenNumber="ngModel"
          oninput="this.value = this.value.replace(/[^0-9]/g, '');"
          [(ngModel)] = "value"
          [placeholder] = "placeholder"
          minlength = "11"
          maxlength = "11"
          [required] = "required">
  <div *ngIf = "citizenNumber.invalid && (citizenNumber.dirty || citizenNumber.touched)"
      class = "form-text text-danger">
      <small *ngIf = "citizenNumber.errors.required">This field is required.</small>
      <small *ngIf = "citizenNumber.errors.minlength">This field must be 11 characters.</small>
      <small *ngIf = "citizenNumber.errors.invalidTc">This is not a citizen number</small>
  </div>
</div>

公民号
此字段必填。
此字段必须为11个字符。
这不是公民号码
这里是一个更新的


希望有帮助

谢谢你的回答。我也试过按键,我知道它是有效的。我的问题是,keydown和keyup在android chrome上不起作用。由于它是一个网站,通常在mobileOk上使用。我会看一看,通过在您的值设置程序中进行一些筛选,它似乎在您的stackblitzString.replace中运行良好。因此,多次按将输入的值。我不明白您的意思,通过这样的过滤,我无法输入任何字母string。每次调用setter时都会调用replace,也就是说,每次输入字母时,如果您在其中粘贴包含字母的字符串,它也会起作用。我添加了一个更新的stackblitz,你有错误吗?问题是我使用公民号组件的形式。如果您查看app.component html,则当您在输入10个数字后输入字符串值时,父窗体将有效,尽管ngModel不会更改。