Angular 如何在调用 ngOnInit 上的补丁值后格式化响应式 FormControls 值

Angular How to Format Reactive FormControls Values after Invoking Patch Value on ngOnInit

我想在初始响应首次更新表单时格式化特定输入字段,但我不知道如何进行初始格式化。

下面的例子是我试听 ngModelChange 的一次尝试。如果您在 FormControl 上设置值或输入不接受值,这将创建一个无限循环,但它得到了我想在父组件收到初始响应后更新格式的想法。下面是我如何使用用户事件处理格式化之后,这是有效的。

import { Directive, HostListener, ElementRef } from '@angular/core';
import { DecimalPipe } from '@angular/common';
import { FormGroup, NgControl } from '@angular/forms';

@Directive({
  selector: '[cfFloat]',
  providers: [DecimalPipe]
})
export class FloatDirective {
  public element: HTMLInputElement;

  constructor(
    private elementRef: ElementRef,
    private decimalPipe: DecimalPipe,
    private ngControl: NgControl
  ) {
    this.element = this.elementRef.nativeElement;
  }

  // ISSUE: this is not the proper event to listen to for a single 
  // initial formatting of any field with this directive, but I 
  // can't figure out how you would do the equivalent to this???
  @HostListener('ngModelChange', ['$event'])
  onModelChange(event: Event) {
    let value = this.element.value.replace(/[^\d\.]+/g, '');
    value = this.decimalPipe.transform(value, '1.2-2');
    //this.ngControl.control.setValue(value); // infinite loop, blows stack
    this.element.value = value; // prevents changes from being made
  }

  @HostListener('blur', ['$event'])
  onBlur(event: KeyboardEvent) {
    let value = this.element.value.replace(/[^\d\.]+/g, '');
    value = this.decimalPipe.transform(value, '1.2-2');
    this.element.value = value; // format for user, but don't change model
  }

  @HostListener('focus', ['$event'])
  onFocus(event: KeyboardEvent) {
    const input = event.target as HTMLInputElement;
    input.value = this.trim(input.value); // format for user, but don't change model
  }

}

现在我能想到的唯一方法是遍历页面中的所有输入以强制聚焦,让它们格式化,然后再次将表单设置为不受影响,这是一个可怕的解决方案.

我最终在 NgControl 上使用了 valueChanges,然后在收到表单初始回复后取消订阅。它没有点击,直到 VSCode 显示 valueChanges 是一个 Observable。

public ngOnInit() {
  const handle = this.ngControl.valueChanges
    .subscribe((value: string) => {
      this.element.value = this.decimalPipe.transform(value, '1.2-2');
      handle.unsubscribe();
    });
}