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

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

问题描述

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

I've put together a currency attribute directive on a ReactiveForm FormControl that uses @HostListener on an input event (onKeyDown) to remove all invalid characters (letters and symbols) as they are typed into the input, but allows numbers and decimals. BUT, if you type an invalid character (ie. a) into an empty input field and it gets removed by the directive, the model is not updated.

我使用货币指令添加了一个 plunker 设置.理解我的问题的步骤:

I've added a plunker setup using the currency directive. Steps to follow to understand my question:

  1. type 123a 你不会在输入中得到 a 因为不允许使用字母,并且按钮被禁用,因为表单无效(好)
  2. 输入 123.456 你在输入中没有得到 6,因为只允许 2 个小数位,并且按钮被禁用,因为表单无效(好)
  3. type a 你在输入中没有得到 a,但是由于模型认为它有一个 a,所以启用了对接即使用户界面没有显示它(坏)
  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)

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

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.

这是一个在 AngularJS 中使用 ngModel 验证器和解析器管道modelValue$setViewValue$ 很容易解决的问题render() 更新并强制 AngularJS 运行 $digest.你如何在 Angular 中做到这一点?

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

推荐答案

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

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 基于智能和哑组件的使用,使用 EventEmitter 实际上是一个更好的解决方案,它将值从输入传递给父表单 -plunker(感谢 Todd Motto 和他的 Ultimate Angular 课程)

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天全站免登陆