2016-07-22 7 views
8

私は、コントローラ内のエンティティにマップされた入力フィールドをngModel双方向バインディングで持っています。角度2は、入力フィールドの空の文字列値としてnullを設定します。

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

私は私のコントローラを初期化すると、私はこのエンティティを持っている:

{ one_attribute: null } 

ユーザーがフィールドに記入し始めたが、すぐにフォームを送信していないと、フィールドを空にした場合、私のエンティティが更新されます

{ one_attribute: "" } 

空の文字列をnullに自動的に変更するように定義することはできますか?

+0

ところで、フィールドにキーアップイベントを送信または追加する前に、自分のエンティティを消去できることがわかっています。しかし、私はそれのためだけにコードを書くことなくこれをしたいと思います。 – jobou

+0

私はこれを自動的に行うものはないと思います。ただし、valueプロパティとinputイベントに対して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

すべての入力をマークする必要がない場合は、[my answer](https://stackoverflow.com/a/46835559/1409101)を参照してください。 –

+1

インターセプタは4.3.4に戻っていますので、このためのディレクティブを書く必要はありません。 –

-2

私はそれをグローバルに行っています。しかし、100%ではありません。私はangle 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); 
} 

これまでのところとても良いです。私はそれを見つけるまで、私はこのようtransformEmptyStringAsNullを実装しているので、しかし、私は、AngularJSのように何か良いtransformRequestを発見していない:

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

私はそれは私が再び解析するために戻って余分な文字列化を行うような方法で醜いと知っています。しかし、私はアプリケーションの残りの部分で何もする必要はありません。

+0

私はHttpを混乱させることなく、それをグローバルに行う方法を考え出しました。詳細は、[my answer](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); 
     }); 
    } 
} 

これは、角度4.4.5で私にとって素晴らしい仕事です。

+0

まだ迎撃器でそれを行う方が良いと思います –

+1

私は同意しません。私の意図は、症状ではなく原因を修正することです。これにより、特定の空の値を 'undefined'に変更して、それらがまったく送信されないようにするかどうかを制御することもできます。 –

関連する問題