Angular将指令与@HostListener一起使用以更新ReactiveForm的输入值会将输入设置为ngValid而不是ngInvalid [英] Angular Using Directive with @HostListener to Update Input Value of ReactiveForm is Setting Input to ngValid Instead of ngInvalid

查看:73
本文介绍了Angular将指令与@HostListener一起使用以更新ReactiveForm的输入值会将输入设置为ngValid而不是ngInvalid的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

我使用货币指令添加了 plunker 设置.要了解我的问题,请按照以下步骤操作:

  1. 键入123a,因为不允许输入字母,因此在输入中没有得到a,并且由于表格无效(好)
  2. ,该按钮被禁用了
  3. 键入123.456,由于仅允许使用小数点后两位,因此在输入中没有得到6,并且由于表格无效(好)
  4. 键入a,您不会在输入中得到a,但是启用了对接,因为即使用户界面未显示,该模型仍认为该接口中具有a(不好)

您可以通过单击按钮并在控制台中查看并记录this.form.value并显示{ amount: 'a' }来验证模型是否未更新.如果接下来输入有效字符,则模型将仅包含该字符,并且a将被删除.因此,只有在这种情况下,才能正确更新模型.

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

这是来自我的attribute指令的代码段,该代码段成功地修剪了不需要的字符:

@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;
}

解决方案

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

基于智能和愚蠢组件的使用,使用EventEmitter实际上是更好的解决方案,它可以将值从输入传递给父表单-plunker setup using the currency directive. Steps to follow to understand my question:

  1. type 123a you don't get an a in the input since no letters are allowed, and the button is disabled since the form is invalid (good)
  2. type 123.456 you don't get a 6 in the input since only 2 decimal places are allowed, and the button is disabled since the form is invalid (good)
  3. type a you don't get a a in the input, BUT the butt is enabled since the model thinks it has an a in it even though the UI doesn't display it (bad)

You can verify the model is not update by clicking the button and looking in the console, which logs this.form.value, and displays { amount: 'a' }. If you type a valid character next the model will only contain that character and a will have been removed. So it is only in this case that the model is not updated properly.

This was an issue easily solved in AngularJS using ngModel validator and parser pipes, the modelValue, $setViewValue, and $render() to update and force AngularJS to run a $digest. How do you do this in Angular?

This is a snippet from my attribute directive that trims out the unwanted characters successfully:

@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;
}

解决方案

So I did figure out a solution for this using NgControl where I injected private ngControl: NgControl then accessed its control property this.ngControl.control.patchValue(newValue);, which updates the input fields model in a ReactiveForm in my onKeyDown event - see plunker

BUT based on the use of smart and dumb components the use of an EventEmitter is actually a better solution that passes up the value to the parent form from the input - plunker (thanks to Todd Motto and his Ultimate Angular courses)

这篇关于Angular将指令与@HostListener一起使用以更新ReactiveForm的输入值会将输入设置为ngValid而不是ngInvalid的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆