【问题标题】:Why set empty string as null in reactive form become empty string为什么在反应形式中将空字符串设置为 null 变成空字符串
【发布时间】:2020-01-14 02:00:19
【问题描述】:

我正在尝试将每个字符串输入转换为空值。 所以我创建了一个指令来监听每个更改并将 null 分配给空字符串。

这里是 HTML

<form [formGroup]="form" class="mt-4 p-2" (ngSubmit)="onSubmit()">
  <input nbInput fullWidth fieldSize="small" shape="semi-round" formControlName="AuthorityNum" EmptyToNull>
</form>

这是指令代码:

import { Directive, Input, HostListener, ElementRef } from 
'@angular/core';

@Directive({
selector: '[EmptyToNull]'
})
export class NullValueDirective {

 constructor() {
 }

 @HostListener('change', ['$event.target.value']) onKeyDowns(value) {
 if (value === '') {
  value = null;
  console.log(value) // print: null
  }
 }
}

好像把值改成null了

但是当我提交表单并检查 form.value 时,它​​再次显示为空字符串。

为什么?

更新

这是我的提交功能:

onSubmit() {
 // TODO: Send to server
  this.form.value.AuthorityNum === '' // true
  }

这是 stackblitz 的代码:https://stackblitz.com/edit/angular-ilcg7y

【问题讨论】:

  • 可以添加提交功能吗? value 是主机侦听器中的局部变量,因此更改内部的值不会改变外部的任何内容。
  • 我认为您需要将指令返回的值绑定到相应的表单元素。
  • 但看起来该值仍未设置为您的表单。你能为此创建一个堆栈闪电战吗?
  • 你说得对。我更新了帖子。
  • 我在帖子中添加了 stackblitz

标签: angular typescript events directive


【解决方案1】:

您的代码有几个问题:

  1. 指令需要返回值,以便可以绑定到相应的表单控件:

    export class NullValueDirectiveDirective {
    
       @Output('EmptyToNull') response = new EventEmitter<string>();
    
       @HostListener('keyup', ['$event']) onKeyDowns(event: KeyboardEvent) {
          this.response.emit(null);
       }
    }
    
  2. 接下来在您的模板上,您需要绑定到 emitted 值:

    <input  formControlName="AuthorityNum" 
    (EmptyToNull) = "form.controls.AuthorityNum.value = $event">
    

【讨论】:

    【解决方案2】:

    指令代码:

    import { Directive, HostListener, Self } from '@angular/core';
    import { NgControl } from '@angular/forms';
    
    @Directive({ selector: '[EmptyToNull]' })
    export class EmptyToNullDirective {
      constructor(@Self() private ngControl: NgControl) {}
    
      @HostListener('keyup', ['$event']) onKeyDowns(event: KeyboardEvent) {
        if (this.ngControl.value?.trim() === '') {
            this.ngControl.reset(null);
        }
      }
    }
    

    模板:

    <input nbInput fullWidth fieldSize="small" shape="semi-round" formControlName="AuthorityNum" EmptyToNull>
    

    【讨论】:

      【解决方案3】:

      我正在尝试使用 EmptyToNull 指令了解您的目标。

      如果您想避免在表单中传递空值,则可以在 ts 中构建表单时更好地使用验证器:

      this.form = this.formbuilder.group({
                     date: [''],
                     AuthorityNum: ['', [Validators.required]],
                  });
      

      查看更多关于验证器的信息:https://angular.io/api/forms/Validators

      提交表单时,您还可以检查值是否填充了您设置的验证器:

       onSubmit() {
          Object.keys(this.form.controls).forEach(field => {
             let control = this.form.get(field);
                     control.markAsTouched({
                         onlySelf: true
                     });
                     control.updateValueAndValidity();
             });
       }
      

      您还可以在提交表单或检测表单更改时在 TS 中尝试以下方法:

      this.form.reset({
              date: { value: '' },
              AuthorityNum: { value: null }
      });
      

      甚至应用在你的指令中:

      this.form.controls['AuthorityNum'].setValue(null);
      

      希望对您有所帮助!

      【讨论】:

      • 我有一个带有嵌套动态输入的非常大的表单。该表单用于测试,因此我需要客户端能够发送空字符串和 null,因此验证器不会帮助我,因为 null 对此有效。我可以像您在帖子中所做的那样循环所有属性并检查空字符串并分配 null 但我不知道如何循环所有属性,因为它们的一部分是带有嵌套属性的数组..
      • 如果您知道哪些字段接受数组作为可能的值,您可以先遍历每个字段,然后对于那些允许数组的字段检查如何到达数组中的每个内部值以对其进行转换。调试“让控制”。
      猜你喜欢
      • 1970-01-01
      • 2015-03-11
      • 2013-12-28
      • 2010-09-17
      • 2017-11-05
      • 2012-01-25
      • 1970-01-01
      • 2016-01-31
      • 1970-01-01
      相关资源
      最近更新 更多