Set null as empty string value for input field

前端 未结 3 911
囚心锁ツ
囚心锁ツ 2020-12-15 05:33

I have an input field mapped to an entity in my controller with a ngModel 2-way binding:

&         


        
相关标签:
3条回答
  • 2020-12-15 06:12

    After viewing a bunch of answers about ValueAccessor and HostListener solutions, I made a working solution (tested with 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);
      }
    }
    

    Then use it that way on your input fields:

    <input [(ngModel)]="bindedValue" nullValue/>
    
    0 讨论(0)
  • 2020-12-15 06:27

    I have done it globally. But its not 100%. I could not find the method where angular 4 call JSON.stringify on the body. I'm hoping someone could help out here. Until the new HttpClient in 4.3 is out I continue to use a wrapper class for the Http service. I do this because no interceptors has been present in Angular2 and forward. My wrapper looks something like this.

    @Injectable()
    export class MyDao {
    constructor(private http: Http) {
    }
    public get(options?:MyRequestOptions){...}
    public post(url:string,body,options?:MyRequestOptions){
       let reqOptions = new BaseRequestOptions();
       reqOptions.url = url;
       reqOptions.params= this.processParams(options);
       reqOptions.header= this.processHeaders(options); //ex. add global headers
       reqOptions.body=this.removeEmptyStringsInBody(body);
       this.http.post(options);
    }
    

    So far so good. But I have not found any good transformRequest as in AngularJS, so until i find it I have implemented transformEmptyStringAsNull as this:

     private removeEmptyStringsInBody(body:any) {
        let bodyTemp= JSON.stringify(body, function (key, value) {
            return value === "" ? null : value
        });
        return JSON.parse(bodyTemp);
    }
    

    I know it's ugly in the way that I will do an extra stringify back to parse again. But I don't need to do anything in the rest of the application.

    0 讨论(0)
  • 2020-12-15 06:28

    I just formed this solution after much research. It's kind of hacky since the Angular team doesn't recommend extending DefaultValueAccessor, but it automagically works for every input without having to mark each one individually.

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

    This is working great for me on Angular 4.4.5.

    0 讨论(0)
提交回复
热议问题