1

我以反应形式向字段添加了一个浮点指令,该指令将逗号添加到每 1000 个字段,并附.00加到字段值,专门用于 UI 中的可读性,效果很好。

  • onBlur 添加格式
  • onFocus 删除格式

当表单加载现有值时,我希望对这些值进行格式化,因此我将其添加到我的浮点指令中,以便在使用setValueor填充表单字段时对值进行一次格式化patchValue,效果很好。

浮点指令的片段

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.

我知道patchValue并且通过文档setValue直接链接到,但是有没有办法听或改变而不是听?或者有没有另一种方法可以让它工作,但仍然有现有的功能,因为即使只是听,也意味着一次性格式订阅仍然有效。valueChangesemitEvent setValuepatchValuevalueChangessetValuepatchValue

浮点指令

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');
  }

}
4

1 回答 1

1

好的,想通了。不是一个可怕的修复,但似乎它可能会更优雅......总是提出建议。

private onInitFormatHandler: Subscription; // <-- ADDED HANDLER AS MEMBER VARIABLE INSTEAD

@HostListener('focus', ['$event'])
onFocus(event: KeyboardEvent) {

  // Remove initial formatting subscription since no patch of the value has
  // occurred, and is no longer likely to occur if the user is actively
  // applying focus
  // ---
  // NOTE: Not unsubscribing causes formatting to occur on dynamically added
  // fields on the first change of the input value prior to blur
  if (!this.onInitFormatHandler.closed) { // <-- ADDED CHECK AND EXTRA UNSUBSCRIPTION
    this.onInitFormatHandler.unsubscribe();
  }

  const float = this.getFloat();
  if (float) {
    this.element.value = this.replace(float);
  }
}

public ngOnInit() {
  this.formatFloat();
}

/**
 * Format the input value only once after the initial form response has
 * patched the model.
 * ---
 * NOTE: Format handler is stored and unsubscribed either on valueChange, or
 * if focus is applied to the field, whichever occurs first.
 */
private formatFloat() {
  this.onInitFormatHandler = this.ngControl.valueChanges // <-- UPDATED HANDLER TO BE MEMBER VARIABLE
    .subscribe((value: string) => {
      const float = this.getFloat();
      if (float) {
        this.element.value = this.format(value);
      }
      this.onInitFormatHandler.unsubscribe(); // <-- UPDATED HANDLER TO BE MEMBER VARIABLE
    });
}
于 2017-05-25T21:51:37.193 回答