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();
});
}
我想在初始响应首次更新表单时格式化特定输入字段,但我不知道如何进行初始格式化。
下面的例子是我试听 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();
});
}