Angular 4 监听 setValue 或 patchValue 而不是使用 valueChanges
Angular 4 Listen for setValue or patchValue instead of using valueChanges
我在反应形式的字段中添加了一个浮点指令,每 1000 个添加一个逗号,并将 .00
附加到字段值,专门用于 UI 中的可读性,效果很好。
- onBlur 添加格式
- onFocus 删除格式
当表单加载现有值时,我希望对这些值进行格式化,所以我将其添加到我的浮点指令中,以便在使用 setValue
或 [=15= 填充表单字段时对值进行一次格式化],效果很好。
浮点指令的片段
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();
});
}
** Added the full directive below, but this is only part that really matters.
但是,如果您在填写空表单时动态地将表单字段添加到 FormArray,这将不会触发一次性格式设置,因此您在字段中键入的第一个数字会添加格式设置。例如,打开一个空表单,单击一个按钮以添加一个动态字段,在该字段中键入 1
会触发一次 valueChange
并且输入现在有 1.00
并且用户将继续输入 1.001244
而不是 11244
.
我知道 patchValue
和 setValue
通过 emitEvent
docs 直接链接到 valueChanges
,但是有没有办法监听 setValue
或 patchValue
改变而不是监听 valueChanges
?或者有另一种方法可以使它工作,但仍然具有现有功能,因为即使只听 setValue
和 patchValue
也意味着一次性格式订阅仍然有效。
浮点指令
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');
}
}
好的,明白了。不是一个可怕的修复,但似乎它可能更优雅......总是征求建议。
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
});
}
我在反应形式的字段中添加了一个浮点指令,每 1000 个添加一个逗号,并将 .00
附加到字段值,专门用于 UI 中的可读性,效果很好。
- onBlur 添加格式
- onFocus 删除格式
当表单加载现有值时,我希望对这些值进行格式化,所以我将其添加到我的浮点指令中,以便在使用 setValue
或 [=15= 填充表单字段时对值进行一次格式化],效果很好。
浮点指令的片段
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();
});
}
** Added the full directive below, but this is only part that really matters.
但是,如果您在填写空表单时动态地将表单字段添加到 FormArray,这将不会触发一次性格式设置,因此您在字段中键入的第一个数字会添加格式设置。例如,打开一个空表单,单击一个按钮以添加一个动态字段,在该字段中键入 1
会触发一次 valueChange
并且输入现在有 1.00
并且用户将继续输入 1.001244
而不是 11244
.
我知道 patchValue
和 setValue
通过 emitEvent
docs 直接链接到 valueChanges
,但是有没有办法监听 setValue
或 patchValue
改变而不是监听 valueChanges
?或者有另一种方法可以使它工作,但仍然具有现有功能,因为即使只听 setValue
和 patchValue
也意味着一次性格式订阅仍然有效。
浮点指令
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');
}
}
好的,明白了。不是一个可怕的修复,但似乎它可能更优雅......总是征求建议。
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
});
}