2017-03-06 40 views
3

有沒有人知道如何聲明ASYNC驗證方法自定義字段的類別如何將一個異步驗證器添加到CUSTOM字段?

現在我在validate()方法同步驗證

@Component({ 
    selector: 'my-field', 
    template: `<p>Some markup</p>`, 
    providers: [ 
    { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => MyFieldComponent), multi: true }, 
    { provide: NG_VALIDATORS, useExisting: forwardRef(() => MyFieldComponent), multi: true } 
    ] 
}) 
export class MyFieldComponent implements ControlValueAccessor { 

    validate(c: FormControl) { 
    // return null or error 
    } 

    // Rest of the code omitted for brevity 
    // writeValue(), registerOnChange()... 
} 

但是即使我添加NG_ASYNC_VALIDATORS使用相同的語法與上述供應商,它不會讓我申報的東西像validateAsync()方法。

除非......這兩種類型的驗證目標的validate()方法,我需要做的這個方法既我的同步和異步驗證回一大觀察到(可能是包裝的多個錯誤的鍵)?我不太確定這一點。

邊注:有什麼我能得到的工作是直接宣佈異步驗證在供應商,無論是內嵌useValue或具有useClass一個單獨的類。但我希望作爲組件類別useExisting的方法。

+0

什麼是'FieldEntityReferenceComponent'? – yurzui

+0

對不起,複製粘貼出錯了......應該說'MyFieldComponent' – AngularChef

回答

3

我不完全明白你的要求是什麼,但我可以給你一些想法,也許會幫助你。

所以我們開始實現ControlValueAccessorValidator(同步)我們的自定義字段:

@Component({ 
    selector: 'my-field', 
    template: `<p>Some markup</p>`, 
    providers: [ 
    { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => MyFieldComponent), multi: true }, 
    { provide: NG_VALIDATORS, useExisting: forwardRef(() => MyFieldComponent), multi: true } 
    ] 
}) 
export class MyFieldComponent implements ControlValueAccessor, Validator { 
    onChange = (_: any) => { }; 
    onTouched =() => { }; 

    constructor(private _renderer: Renderer, private _elementRef: ElementRef) { } 

    writeValue(value: any): void { 
    const normalizedValue = value == null ? '' : value; 
    this._renderer.setElementProperty(this._elementRef.nativeElement, 'value', normalizedValue); 
    } 

    registerOnChange(fn: (_: any) => void): void { this.onChange = fn; } 
    registerOnTouched(fn:() => void): void { this.onTouched = fn; } 

    validationResult: any; 

    validate(c: FormControl) { 
    this.validationResult = { 'sync': true }; 
    return null; 
    } 
} 

該聲明指令將實現AsyncValidator後:

@Directive({ 
    selector: 'my-field[formControlName],my-field[ngModel]', 
    providers: [{ 
    provide: NG_ASYNC_VALIDATORS, 
    useExisting: forwardRef(() => CustomAsyncValidator), 
    multi: true 
    }] 
}) 
class CustomAsyncValidator implements AsyncValidator { 

    valueAccessor: MyFieldComponent; 

    constructor(@Optional() @Self() @Inject(NG_VALUE_ACCESSOR) valueAccessors: ControlValueAccessor[]) { 
    this.valueAccessor = valueAccessors.find(x => x.constructor === MyFieldComponent) as MyFieldComponent; 
    } 

    // the same as above. I would use it 
    // constructor(@Self() private valueAccessor: MyFieldComponent) {} 


    /** 
    * presents global validation result async + sync 
    */ 
    validate(control: AbstractControl): Observable<any> { 
    return Observable.fromPromise(fakeAsyncValidator(1000)(control)).map(asyncResult => { 
     return Object.assign({}, asyncResult, this.valueAccessor.validationResult); 
    }); 
    } 
} 


function fakeAsyncValidator(timeout: number = 0) { 
    return (c: AbstractControl) => { 
    let resolve: (result: any) => void; 
    const promise = new Promise(res => { resolve = res; }); 
    const res = { 'async': false }; 
    setTimeout(() => resolve(res), timeout); 
    return promise; 
    }; 
} 

在指令上面我們使用與我們的自定義字段(my-field)相同的選擇器,提供NG_ASYNC_VALIDATORS並在構造函數中注入現有組件(您可以注意到兩個選項)。

最後我們在這個指令中有validate方法,它試圖做類似你想要的東西。

Plunker Example

+0

謝謝你的回答和你的時間,yurzui。其基本原理是,如果驗證者只能被一個字段和一個字段使用,那麼將其作爲字段代碼的一部分會感覺更加緊密。另外,由於我們討論的是需要使用'Http'的異步驗證器,它*必須*屬於某種支持依賴注入(指令或組件)的Angular構造;它不可能僅僅是一種功能或類別。現在,您確實提供了一些有關您的答案的見解,並且我有幾個問題......(待續下一評論) – AngularChef

+0

讓指令與字段的選擇器匹配的好主意。這樣,該指令就會自動應用到自定義字段。現在你可以在'CustomAsyncValidator'的構造函數中解釋可選注入嗎?我得到它允許異步驗證程序訪問同步驗證程序的結果,但它確實是必需的嗎?如果'validate()'方法(sync + async)分別返回它們的值**,那麼它們會不會自動合併? – AngularChef

+0

是的。我正在訪問同步驗證程序,「@ Options」用於防止未定義的錯誤。我只注意到angular2是如何做到的https://github.com/angular/angular/blob/4.0.0-rc.2/modules/%40angular/forms/src/directives/reactive_directives/form_control_name.ts#L102我是不確定自動合併它。 Angular使用相同的技術('這個好主意讓指令匹配字段的選擇器)在指令之間進行通信https://github.com/angular/angular/blob/4.0.0-rc.2/modules/% 40angular/forms/src/directives/ng_control_status.ts#L45-L48 – yurzui

相關問題