为啥在反应形式中将空字符串设置为 null 变成空字符串

Posted

技术标签:

【中文标题】为啥在反应形式中将空字符串设置为 null 变成空字符串【英文标题】: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 【参考方案1】:

您的代码有几个问题:

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

    export class NullValueDirectiveDirective 
    
       @Output('EmptyToNull') response = new EventEmitter<string>();
    
       @HostListener('keyup', ['$event']) onKeyDowns(event: KeyboardEvent) 
          this.response.emit(null);
       
    
    

    接下来在您的模板上,您需要绑定到 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 但我不知道如何循环所有属性,因为它们的一部分是带有嵌套属性的数组.. 如果您知道哪些字段接受数组作为可能的值,您可以先遍历每个字段,然后对于那些允许数组的字段检查如何到达数组中的每个内部值以对其进行转换。调试“让控制”。

以上是关于为啥在反应形式中将空字符串设置为 null 变成空字符串的主要内容,如果未能解决你的问题,请参考以下文章

在 Spring MVC 中将值设置为 NULL 而不是空字符串

mybatis 空字符串 为啥变为null

oracle存空字符串怎么会变成null

mysql 为啥我设置一个表的字段not null,为啥还可以插空?

当函数的参数为​​“未定义”或“空”或“”(空字符串)时,如何设置函数参数的默认值?

java中做字符串非空判断,为啥要同时判断字符串不为null和不等于空串?