Angular 2将null设置为输入字段的空字符串值

job*_*bou 15 angular2-template angular

我有一个输入字段映射到我的控制器中的实体与input双向绑定.

<input type="text" [(ngModel)]="entity.one_attribute" />
Run Code Online (Sandbox Code Playgroud)

当我初始化我的控制器时,我有这个实体:

{ one_attribute: null }
Run Code Online (Sandbox Code Playgroud)

如果用户开始填写该字段但未立即提交表单并清空该字段,则我的实体将更新为:

{ one_attribute: "" }
Run Code Online (Sandbox Code Playgroud)

是否可以定义空字符串应自动更改为null?

job*_*bou 18

观看了一堆有关答复后ValueAccessorHostListener解决方案,我做了一个工作液(用RC1测试):

import {NgControl} from "@angular/common";
import {Directive, ElementRef, HostListener} from "@angular/core";

@Directive({
  selector: 'input[nullValue]'
})
export class NullDefaultValueDirective {
  constructor(private el: ElementRef, private control: NgControl) {}

  @HostListener('input', ['$event.target'])
  onEvent(target: HTMLInputElement){
    this.control.viewToModelUpdate((target.value === '') ? null : target.value);
  }
}
Run Code Online (Sandbox Code Playgroud)

然后在输入字段中使用它:

<input [(ngModel)]="bindedValue" nullValue/>
Run Code Online (Sandbox Code Playgroud)

  • 对于不应该使用ngModel的反应形式,这等效于什么? (2认同)

use*_*596 7

有一种方法可以为所有组件修复此问题,该方法不会与其他组件冲突ValueAccessor,并且不需要在任何地方添加指令。TLDR:将其添加到您的 AppModule 中:

    DefaultValueAccessor.prototype.registerOnChange = function (fn: (_: string | null) => void): void {
      this.onChange = (value: string | null) => {
        fn(value === '' ? null : value);
      };
    };
Run Code Online (Sandbox Code Playgroud)

总而言之,这是一个已知的角度问题,报告如下:https: //github.com/angular/angular/issues/45317 并且除非您使用这个小技巧,否则无法修复,因为这里解释了很多旧问题:https ://github.com/angular/angular/issues/3009 这可以防止全局覆盖 Angular 的默认行为。希望能帮助到你。@taylor-buchanan 的回答让我走上了正轨


Tay*_*nan 5

我经过多次研究后才形成了这个解决方案 这是一种hacky,因为Angular团队不建议扩展DefaultValueAccessor,但它自动适用于每个输入,而不必单独标记每个输入.

import { Directive, forwardRef, Renderer2, ElementRef, Input } from '@angular/core';
import { DefaultValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';

export const VALUE_ACCESSOR: any = {
    provide: NG_VALUE_ACCESSOR,
    useExisting: forwardRef(() => InputExtensionValueAccessor),
    multi: true
};

@Directive({
    selector: 'input:not([type]),input[type=text],input[type=password],input[type=email],input[type=tel],textarea',
    host: {
        '(input)': '_handleInput($event.target.value)',
        '(blur)': 'onTouched()',
        '(compositionstart)': '_compositionStart()',
        '(compositionend)': '_compositionEnd($event.target.value)'
    },
    providers: [VALUE_ACCESSOR]
})
export class InputExtensionValueAccessor extends DefaultValueAccessor  {
    // HACK: Allows use of DefaultValueAccessor as base
    // (https://github.com/angular/angular/issues/9146)
    static decorators = null;

    constructor(renderer: Renderer2, elementRef: ElementRef) {
        super(renderer, elementRef, (null as any));
    }

    registerOnChange(fn: (_: any) => void): void {
        super.registerOnChange(value => {
            // Convert empty string from the view to null for the model
            fn(value === '' ? null : value);
        });
    }
}
Run Code Online (Sandbox Code Playgroud)

这对Angular 4.4.5非常有用.

  • @aycanadal 我不认为这是真的。检查 [this](https://stackblitz.com/edit/ngmodel-empty-value)。在 Angular 6 中它仍然设置为空字符串。 (2认同)