如何触发反应式表单值仅在输入模糊时更改订阅并在Angular 2中输入键

时间:2017-10-10 10:04:50

标签: javascript forms angular typescript

我正在处理一个表单,该表单应该仅在输入模糊或输入按键时更新某些ui部分。我是反应形式的忠实粉丝,我试图弄清楚什么是正确的方法。到目前为止,我还没有找到太多反应形式的答案。他们中的大多数都专注于模板驱动的表单。到目前为止我得到了这样的东西:

表单组件动态表单值在运行时更改(无可预测的字段名称)

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

3 个答案:

答案 0 :(得分:2)

您可以组合模糊并将事件输入主题并将其与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"/>

答案 1 :(得分:0)

如果将来有人发现这一点,那么实际上updateOn选项中有一些内置于此的反应形式:

new FormControl('', {updateOn: 'blur'});

这将导致valueChanges和验证,并且仅在模糊时触发

答案 2 :(得分:0)

// component
public ctrl: FormControl = new FormControl(0, {updateOn: 'blur'});

//html
<input [formControl]="ctrl" (keydown.enter)="$event.target.blur()"/>```