2016-07-22 56 views
8

我有一個輸入字段映射到我的控制器中的一個實體,使用ngModel雙向綁定。Angular 2將null設置爲輸入字段的空字符串值

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

當我初始化我的控制器,我有這樣的實體:如果用戶開始填補了該領域,但不會立即提交表單,倒空場

{ one_attribute: null } 

,我的實體更新變成:

{ one_attribute: "" } 

是否可以定義空字符串應該自動更改爲null?

+0

順便說一下,我知道我可以在提交或在我的字段中添加關鍵事件之前清理我的實體。但我想這樣做,而不用爲此編寫任何代碼。 – jobou

+0

我不認爲有什麼會自動做到這一點。但是,您可以將ngModel分割爲值屬性和輸入事件的單獨綁定,如果值爲空字符串,只需將模型設置爲null即可。 –

+1

如何創建一個內部使用'input'的組件,並在其中實現邏輯?這樣你就不需要每次都寫。 –

回答

11

觀看了一堆答案約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); 
    } 
} 

然後用它在你的輸入字段的方法:

<input [(ngModel)]="bindedValue" nullValue/> 
+0

如果您不想標記每個輸入,請參閱[我的答案](https://stackoverflow.com/a/46835559/1409101)。 –

+1

4.3.4中的攔截器,所以你不需要爲此寫一個指令。 –

-2

我已經在全球範圍內做到了。但它不是100%。我無法找到角4在身體上調用JSON.stringify的方法。我希望有人能在這裏幫忙。 直到4.3中新的HttpClient出來,我繼續使用Http服務的包裝類。我這樣做是因爲在Angular2中沒有攔截器,並且前進。我的包裝看起來像這樣。

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

到目前爲止好。但我沒有發現任何好的transformRequest在AngularJS,所以直到我發現我已經實現transformEmptyStringAsNull就象這樣:

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

我知道這是在說我會做一個額外的字符串化回再次解析的方式難看。但是我不需要在應用程序的其他部分做任何事情。

+0

我想出了一種在全球範圍內完成這項工作的方法,而不必惹Http。有關詳細信息,請參閱[我的回答](https://stackoverflow.com/a/46835559/1409101)。 –

3

我經過很多研究才形成這個解決方案。這是一種冒險的since the Angular team doesn't recommend extending 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); 
     }); 
    } 
} 

這對我在Angular 4.4.5上非常有用。

+0

仍然認爲它更好的做在攔截器 –

+1

我不同意。我的意圖是解決問題的原因,而不是症狀。這也允許我控制是否想將某些空值更改爲「未定義」,以防止它們被髮送。 –

相關問題