2017-05-25 58 views
0

我在反應形式的字段中添加了一個浮點指令,每1000個逗號加上一個字段值,並將.00附加到專門用於UI內可讀性的字段值, 。Angular 4監聽setValue或patchValue,而不是使用valueChanges

  • 的onblur增加格式化
  • 的onfocus去除了格式化

加載窗體時與現有的價值,我想這些價值被如此格式化我將此添加到我的浮點指令,以便值格式化一次作爲表單字段使用setValuepatchValue,這真是棒極了填補。

段從浮點指令

public ngOnInit() { 
    this.formatFloat(); 
} 

private formatFloat() { 
    const handle = this.ngControl.valueChanges 
    .subscribe((value: string) => { 
     const float = this.getFloat(); 
     if (float) { 
     this.element.value = this.format(value); 
     } 
     handle.unsubscribe(); 
    }); 
} 

**添加下面的完整指令,但是這是真正重要的一部分。

但是,如果您在填寫空表單時動態地向FormArray添加表單字段,則不會觸發一次性格式設置,因此您鍵入字段的第一個數字將添加格式。例如,打開了一個空的表單,點擊一個按鈕來添加一個動態字段中,鍵入1進入該領域觸發一次valueChange和輸入現在有1.00,用戶將繼續打字1.001244而不是11244

我知道patchValuesetValue直接通過emitEventdocsvalueChanges,但有偵聽setValuepatchValue的變化,而不是傾聽valueChanges的方法嗎?還是有另一種方法可以讓我得到這個工作,但還是有,因爲即使只是聽setValuepatchValue將意味着一個時間格式訂閱仍然活着的現有功能。

浮點指令

import { Directive, HostListener, ElementRef, OnInit } from '@angular/core'; 
import { DecimalPipe } from '@angular/common'; 
import { FormGroup, NgControl } from '@angular/forms'; 

@Directive({ 
    selector: '[cfFloat]', 
    providers: [DecimalPipe] // TODO: why do I need this? 
}) 
export class FloatDirective implements OnInit { 
    public element: HTMLInputElement; 

    constructor(
    private elementRef: ElementRef, 
    private decimalPipe: DecimalPipe, 
    private ngControl: NgControl 
) { 
    this.element = this.elementRef.nativeElement; 
    } 

    @HostListener('blur', ['$event']) 
    onBlur(event: KeyboardEvent) { 
    const float = this.getFloat(); 
    if (float) { 
     this.element.value = this.format(float); 
    } 
    } 

    @HostListener('focus', ['$event']) 
    onFocus(event: KeyboardEvent) { 
    const float = this.getFloat(); 
    if (float) { 
     this.element.value = this.replace(float); 
    } 
    } 

    public ngOnInit() { 
    this.formatFloat(); 
    } 

    private formatFloat() { 
    const handle = this.ngControl.valueChanges 
     .subscribe((value: string) => { 
     const float = this.getFloat(); 
     if (float) { 
      this.element.value = this.format(value); 
     } 
     handle.unsubscribe(); 
     }); 
    } 

    private getFloat(): string { 
    const value = this.element.value; 
    const float = this.replace(value); 
    // Only perform an action when a floating point value exists and there are 
    // no errors, otherwise leave the erroneous value to be fixed manually by 
    // ignoring an action 
    if (value && float && this.checkIsValid()) { 
     return float; 
    } 
    } 

    private checkIsValid(): boolean { 
    return !this.ngControl.control.errors; 
    } 

    private replace(value: string): string { 
    return value.replace(/[^\d\.]+/g, ''); 
    } 

    private format(value: string) { 
    return this.decimalPipe.transform(value, '1.2-2'); 
    } 

} 

回答

0

好了,想通了這一點。不是一個可怕的修復,但看起來它可能是更優雅,也許......始終尋求建議。

private onInitFormatHandler: Subscription; // <-- ADDED HANDLER AS MEMBER VARIABLE INSTEAD 

@HostListener('focus', ['$event']) 
onFocus(event: KeyboardEvent) { 

    // Remove initial formatting subscription since no patch of the value has 
    // occurred, and is no longer likely to occur if the user is actively 
    // applying focus 
    // --- 
    // NOTE: Not unsubscribing causes formatting to occur on dynamically added 
    // fields on the first change of the input value prior to blur 
    if (!this.onInitFormatHandler.closed) { // <-- ADDED CHECK AND EXTRA UNSUBSCRIPTION 
    this.onInitFormatHandler.unsubscribe(); 
    } 

    const float = this.getFloat(); 
    if (float) { 
    this.element.value = this.replace(float); 
    } 
} 

public ngOnInit() { 
    this.formatFloat(); 
} 

/** 
* Format the input value only once after the initial form response has 
* patched the model. 
* --- 
* NOTE: Format handler is stored and unsubscribed either on valueChange, or 
* if focus is applied to the field, whichever occurs first. 
*/ 
private formatFloat() { 
    this.onInitFormatHandler = this.ngControl.valueChanges // <-- UPDATED HANDLER TO BE MEMBER VARIABLE 
    .subscribe((value: string) => { 
     const float = this.getFloat(); 
     if (float) { 
     this.element.value = this.format(value); 
     } 
     this.onInitFormatHandler.unsubscribe(); // <-- UPDATED HANDLER TO BE MEMBER VARIABLE 
    }); 
} 
相關問題