Angular 4侦听setValue或patchValue而不是使用valueChanges

时间:2017-05-25 21:08:57

标签: angular angular-reactive-forms

我已经在一个被动形式的字段中添加了一个浮点指令,该字段为每1000个字符添加逗号,并将.00附加到字段值,专门用于UI中的可读性,效果很好。

  • 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通过valueChanges docs直接与emitEvent相关联,但有没有办法倾听setValue }或patchValue更改而不是收听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');
  }

}

1 个答案:

答案 0 :(得分:1)

好的,想通了。不是一个可怕的解决方案,但似乎可能更优雅......总是提出建议。

{{1}}