Angular使用带有@HostListener的指令更新ReactiveForm的输入值是将输入设置为ngValid而不是ngInvalid

时间:2017-04-12 22:04:50

标签: angular angular-directive

我在ReactiveForm FormControl上汇总了一个货币属性指令,该指令在输入事件(onKeyDown)上使用@HostListener来删除所有无效字符(字母和符号)因为它们被输入到输入中,但允许数字和小数。 但是,如果您在空输入字段中键入无效字符(即a)并且指令删除它,则模型不会更新。

我已使用currency指令添加了plunker设置。要了解我的问题,请遵循以下步骤:

  1. 输入123a您在输入中未获得a,因为不允许使用任何字母,并且因为表单无效而禁用该按钮(好)
  2. 输入123.456您未在输入中获得6,因为只允许2位小数,并且由于表格无效而禁用该按钮(好)< /强>
  3. 键入a您未在输入中获得a,但是对帐已启用,因为模型认为其中包含a,即使用户界面没有&{ #39; t显示(差错)
  4. 您可以通过单击按钮并查看记录this.form.value的控制台并显示{ amount: 'a' }来验证模型是否未更新。如果您键入有效字符,则模型将仅包含该字符,并且a将被删除。因此,只有在这种情况下,模型才能正确更新。

    这是AngularJS中使用ngModel validator and parser pipesmodelValue$setViewValue$render()轻松解决的问题,可以更新并强制AngularJS运行$ digest。你是如何在Angular中做到这一点的?

    这是我的属性指令中的一个片段,它成功地删除了不需要的字符:

    @HostListener('input', ['$event'])
      onKeyDown(event: KeyboardEvent) {
        const input = event.target as HTMLInputElement;
    
        // Only numbers and decimals
        let trimmed = input.value.replace(/[^\d\.,]+/g, '');
    
        // Only a single decimal and choose the first one found
        if (trimmed.split('.').length > 2) {
          trimmed = trimmed.replace(/\.([^\.]*)$/, '$1');
        }
    
        // Cannot start with decimal typed or pasted
        if (trimmed.indexOf('.') === 0) { trimmed = ''; }
    
        // AngularJS "like" solution would be something like:
        // ngModelCtrl.$setViewValue(trimmed);
        // ngModelCtrl.$render();
        // Angular solution is???
    
        input.value = trimmed;
    }
    

2 个答案:

答案 0 :(得分:7)

所以我确实使用NgControl找到了一个解决方案,我注入private ngControl: NgControl然后访问了它的控件属性this.ngControl.control.patchValue(newValue);,它更新了ReactiveForm中的输入字段模型在我的onKeyDown活动中 - 请参阅plunker

基于智能和哑组件的使用

使用EventEmitter实际上是一种更好的解决方案,可以将值从输入传递给父表单 - {{3 (感谢Todd Motto和他的Ultimate Angular课程)

答案 1 :(得分:0)

随着最近的角度4发布,引入了一个新指令来处理这些场景

<input [name]="fullName" pattern="[a-zA-Z ]*" [(ngModel)]="...">

在模式中,您可以指定任何正则表达式

<强> Docs

更新:根据评论,如果您尝试限制用户输入字符,则可以使用自定义指令。

使用以下代码作为指令功能

  @HostListener('keydown') onKeydown() {
      let value= this.el.nativeElement.value;
     let key= value.charCodeAt(value.length -1])
     let strippedString ='';
     if(!((key > 64 && key < 91) || (key> 96 && key< 123) || key== 8 || key== 32 || (key>= 48 && key<= 57)){
       strippedString = this.el.nativeElement.value.substring(0,value.length-1)
       this.el.nativeElement.value = strippedString
     }

<强> LIVE DEMO