如何观察Angular 2 NgForm上的触摸事件?

Che*_*149 17 typescript angular2-forms angular

因此能够订阅回调到NgFormvalueChanges观察特性,以反应形式的控制的值的变化.

我需要以相同的方式对用户触摸其中一个表单控件的事件作出反应.

这个类似乎定义了valueChangesObservable,touched属性被定义为一个布尔值.

有没有办法对"控制感动"事件做出反应?

Egg*_*ggy 13

您可以扩展默认FormControl类,并添加markAsTouched将调用本机方法的方法,以及您的副作用.

import { Injectable } from '@angular/core';
import { FormControl, AsyncValidatorFn, ValidatorFn } from '@angular/forms';
import { Subscription, Subject, Observable } from 'rxjs';

export class ExtendedFormControl extends FormControl {
  statusChanges$: Subscription;
  touchedChanges: Subject<boolean> = new Subject<boolean>();

  constructor(
    formState: Object,
    validator: ValidatorFn | ValidatorFn[] = null,
    asyncValidator: AsyncValidatorFn | AsyncValidatorFn[] = null
  ) {
    super(formState, validator, asyncValidator);

    this.statusChanges$ = Observable.merge(
      this.valueChanges,
      this.touchedChanges.distinctUntilChanged()
    ).subscribe(() => {
      console.log('new value or field was touched');
    });
  }

  markAsTouched({ onlySelf }: { onlySelf?: boolean } = {}): void {
    super.markAsTouched({ onlySelf });

    this.touchedChanges.next(true);
  }
}
Run Code Online (Sandbox Code Playgroud)


Val*_*dov 9

ng2没有提供直接的方式来对触摸的事件作出反应.它使用(输入)事件来触发valueChanges事件和(blur)事件来设置AbstractControl的触摸/未触摸 属性.因此,您需要在模板中手动订阅所需的事件,并在组件类中处理它.


mbd*_*vis 7

有同样的问题 - 将这个辅助方法放在一起以提取一个可观察的对象,您可以在一个表单中订阅它,以便在触摸状态更改时收到通知:

// Helper types

/**
 * Extract arguments of function
 */
export type ArgumentsType<F> = F extends (...args: infer A) => any ? A : never;

/**
 * Creates an object like O. Optionally provide minimum set of properties P which the objects must share to conform
 */
type ObjectLike<O extends object, P extends keyof O = keyof O> = Pick<O, P>;


/**
 * Extract a touched changed observable from an abstract control
 * @param control AbstractControl like object with markAsTouched method
 */
export const extractTouchedChanges = (control: ObjectLike<AbstractControl, 'markAsTouched' | 'markAsUntouched'>): Observable<boolean> => {
  const prevMarkAsTouched = control.markAsTouched;
  const prevMarkAsUntouched = control.markAsUntouched;

  const touchedChanges$ = new Subject<boolean>();

  function nextMarkAsTouched(...args: ArgumentsType<AbstractControl['markAsTouched']>) {
    touchedChanges$.next(true);
    prevMarkAsTouched.bind(control)(...args);
  }

  function nextMarkAsUntouched(...args: ArgumentsType<AbstractControl['markAsUntouched']>) {
    touchedChanges$.next(false);
    prevMarkAsUntouched.bind(control)(...args);
  }

  control.markAsTouched = nextMarkAsTouched;
  control.markAsUntouched = nextMarkAsUntouched;

  return touchedChanges$;
}
Run Code Online (Sandbox Code Playgroud)
// Usage (in component file)

...
    this.touchedChanged$ = extractTouchedChanges(this.form);
...

Run Code Online (Sandbox Code Playgroud)

然后我喜欢做merge(this.touchedChanged$, this.form.valueChanges)一个可观察的更新验证所需的所有更改。

  • 有点晚了 - 但不,你只会影响传递给助手的表单实例 (2认同)

ʞᴉɯ*_*ʞᴉɯ 7

我是这样解决的:

this.control['_markAsTouched'] = this.control.markAsTouched;
this.control.markAsTouched = () => {
  this.control['_markAsTouched']();
  // your event handler
}
Run Code Online (Sandbox Code Playgroud)

基本上我正在markAsTouched覆盖FormControl.