Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Set null as empty string value for input field

Tags:

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

<input type="text" [(ngModel)]="entity.one_attribute" /> 

When I initialize my controller, I have this entity:

{ one_attribute: null } 

If a user starts to fill in the field but does not submit the form immediately and empties the field, my entity is updated to become:

{ one_attribute: "" } 

Is it possible to define that empty string should be changed to null automatically?

like image 355
jobou Avatar asked Jul 22 '16 13:07

jobou


People also ask

Can I assign a null value to a string?

Any type is known as nullable if you can assign a value or null to this variable it means that the type will have no value. In C# all reference types like string are of a nullable type, but the other types like int32 are not nullable type.

Can a string be empty and null?

A string refers to a character's sequence. Sometimes strings can be empty or NULL. The difference is that NULL is used to refer to nothing. However, an empty string is used to point to a unique string with zero length.

Why use null instead of empty string?

If you were to use s , it would actually have a value of null , because it holds absolute nothing. An empty string, however, is a value - it is a string of no characters. Null is essentially 'nothing' - it's the default 'value' (to use the term loosely) that Java assigns to any Object variable that was not initialized.

What is null input?

A field with a NULL value is a field with no value. If a field in a table is optional, it is possible to insert a new record or update a record without adding a value to this field. Then, the field will be saved with a NULL value. Note: A NULL value is different from a zero value or a field that contains spaces.


2 Answers

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/> 
like image 135
jobou Avatar answered Nov 06 '22 19:11

jobou


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.

like image 42
Taylor Buchanan Avatar answered Nov 06 '22 17:11

Taylor Buchanan