2017-10-10 25 views
3

我正在處理一個窗體,該窗體應該僅在輸入模糊時更新某些UI部件或按下輸入按鍵。我是被動形式的忠實粉絲,我正試圖弄清楚什麼是正確的方式。到目前爲止,我還沒有找到太多答案。他們大多集中在模板驅動的表單上。我有這樣的事情至今:如何觸發反應形式valueChanges只對輸入模糊訂閱,然後在angualr 2中輸入密鑰

表單組件動態表單值在運行時更改(沒有可預見的申請名稱)

import { Component, Input, Output, EventEmitter, 
    ChangeDetectionStrategy } from '@angular/core' 
import { FormBuilder, FormGroup, FormControl } from '@angular/forms' 
import { Observable } from "rxjs/Observable" 
import { DEBUG } from '../../../../config/config' 
import * as Debug from 'debug' 

// Interfaces 
import { Foo } from '../../interfaces/foo' 

// Services 
import { FooService } from '../../services/foo.service' 

// Debug 
const debugOff = (...any) => { }, debug = Debug('app:FooCmp') 

@Component({ 
    selector: 'foo-data-cmp', 
    templateUrl: './foo.data.cmp.html', 
    changeDetection: ChangeDetectionStrategy.OnPush, 
    styleUrls: ['./foo.data.cmp.css'] 
}) 
export class FooDataCmp { 

    private _foo: Foo[] = null 
    @Input('foo') 
    set foo(foo: Foo[]) { 
     this._foo = foo 
     DEBUG.input && debug('Input foo:', this._foo) 
    } 
    get foo(): Foo[] { 
     return this._foo 
    } 

    // Forms 
    public fooForm: FormGroup 
    public fooForm$: Observable<any> 
    private updatedFoo: any[] // Updated form values 

    // Subscriptions 
    private subscriptions: any[] = [] 

    constructor(
     private formBuilder: FormBuilder, 
     private fooService: FooService, 
    ) { 
     DEBUG.constr && debug('Construct FooDataCmp') 
    } 

    ngOnInit() { 
     DEBUG.init && debug('Initialise FooDataCmp') 

     // Form 
     this.initFooForm() 
     this.subcribeToFormChanges() 
    } 

    ngOnDestroy() { 
     DEBUG.destroy && debug('Destroy FooDataCmp') 
     this.subscriptions.forEach(sub => sub.unsubscribe()) 
    } 

    private initFooForm() { 
     DEBUG.cmp && debug('Initialise foo form') 

     // Build the form 
     this.fooForm = this.formBuilder.group(this._foo) 

     // Prevent undefined error at first keystroke 
     this.updatedFoo = this._foo 
    } 

    private subcribeToFormChanges() { 
     this.fooForm$ = this.fooForm.valueChanges 
     let sub = this.fooForm$.subscribe(fooForm => { 
      DEBUG.cmp && debug('Form changes fooForm', fooForm) 
      this.updatedFoo = fooForm 
     }) 
     this.subscriptions.push(sub) 
    } 

    /** 
    * <!> Important step in the data update process 
    * Update state store. 
    * Other services/components are subscribed to the state store itself 
    */ 
    public refreshAllFooRelatedData() { 
     DEBUG.cmp && debug('Refresh all foo related data') 
     DEBUG.cmp && debugOff('Updated foo', this.updatedFoo) 
     this.fooService.refreshAllFooRelatedData(this.updatedFoo) 
    } 

    public refreshAllFooRelatedDataOnEnter (e: KeyboardEvent) { 
     if (e.keyCode !== 13) {return} 
     DEBUG.cmp && debug('Refresh all foo related data (on enter)') 
     DEBUG.cmp && debugOff('Updated foo', this.updatedFoo) 
     this.fooService.refreshAllFooRelatedData(this.updatedFoo) 
    } 

    public debugTemplate() { 
     DEBUG.render && debug('Render FooDataCmp') 
    } 

} 

表單模板

<form [formGroup]="fooForm"> 
    <table class="list expiries"> 
      <td *ngFor="let value of foo; let i = index"> 
       <input type="text" [formControlName]="foo[i]" 
        (blur)="refreshAllFooRelatedData()" 
        (keydown)="refreshAllFooRelatedDataOnEnter($event)"> 
      </td> 
    </table> 
</form> 

{{ debugTemplate() }} 

這是一個體面解決方案還是我錯過了一些技巧?我的問題是如果這是做到這一點的正確方法。我一直期待找到一些表單API來處理這個任務。我的方法是建立在表單之上,但如果有任何可用於此任務的情況,我寧願使用完整表單API

+0

*這是一個體面的解決辦法...?*您問我們是否喜歡你沒有,或者這不適合你?如果是這樣,問題究竟在哪裏?反應形式非常好[文檔](https://angular.io/guide/reactive-forms)。 [表單控件](https://angular.io/api/forms/FormControl)也是如此。 –

+0

我的問題是,如果這是做到這一點的正確方法。我一直在尋找一些表單API來處理這個任務。我的方法是建立在表單之上,但如果有任何可用於此任務的情況,我寧願使用完整的表單api。 –

回答

1

您可以將模糊和輸入事件組合到主題中,並將其與valuechange Observable合併,所以只有在模糊或進入時它纔會激發價值。我還沒有完全測試的代碼只是一個想法,我也碰到過類似的情況之前

// component 
 
this.updateField=new Subject() 
 

 
this.form.get('yourfield').valueChanges.withLatestFrom(updateField).map(res=>res[0]).subscribe() 
 

 
//html 
 
<input (blur)="updateField($event)" (keydown)="$event.keyCode == 13?updateField($event):false"/>

+0

這是一個整潔的想法!我知道有些事情可以做得更好。謝謝!該死的,其實我現在意識到我太盲目了......當我修改時我會更新。 Obwarebles Ftw! :d –