[英]How to detect a value change on an input when it is dynamically updated (Angular 6)
I'm using a custom directive and custom pipe to do currency formatting on text inputs. 我正在使用自定义指令和自定义管道对文本输入进行货币格式化。 It works fine with any kind of direct user input (focus, blur, keydown). 它可以与任何类型的直接用户输入(焦点,模糊,抠像)一起正常工作。 However I can't seem to capture the change event when the value is changed dynamically. 但是,当值动态更改时,我似乎无法捕获更改事件。 I also can't find a reliable list of hostlistener events, and don't know of a way to capture any event coming to the input (and thus can't see what event, if any, is happening). 我也找不到可靠的hostlistener事件列表,也不知道捕获输入事件的方式(因此无法看到正在发生的事件)。
Dynamically, the value is being set with patchValue, and I've set emitEvent to true but this appears to do nothing (I assume it's true by default anyway): 动态地,该值是使用patchValue设置的,并且我已经将emitEvent设置为true,但这似乎什么也没做(无论如何我还是假定默认为true):
myInput.patchValue({content: currentContent}, { emitEvent: true });
I could rewrite the currency formatting before the content value is set with patchValue, but this goes against reusability. 我可以在使用patchValue设置内容值之前重写货币格式,但这有损于可重用性。
Here is my directive: 这是我的指令:
import { Directive, HostListener, ElementRef, OnInit } from '@angular/core';
import { CurrencyPipe } from '../pipes/currency.pipe';
@Directive({
selector: '[appCurrency]'
})
export class CurrencyDirective implements OnInit {
constructor(
private elementRef:ElementRef,
private formatcurrencypipe:CurrencyPipe
) { }
ngOnInit(){
//this.elementRef.nativeElement.value = this.formatcurrencypipe.transform(this.elementRef.nativeElement.value);
}
@HostListener("change", ["$event.target.value", "$event"]) onChange(value, event) {
//this.elementRef.nativeElement.value = this.formatcurrencypipe.parse(value);
}
@HostListener("valueChange", ["$event.target.value", "$event"]) onValueChange(value, event) {
console.log('in onValueChange');
//doesn't trigger when the value is changed dynamically
}
@HostListener("focus",["$event.target.value","$event"]) onFocus(value,event) {
console.log('in focus');
this.elementRef.nativeElement.value = this.formatcurrencypipe.parse(value);
if(event.which == 9)
{
return false;
}
this.elementRef.nativeElement.select();
}
@HostListener("blur", ["$event.target.value"]) onBlur(value) {
console.log('in blur');
this.elementRef.nativeElement.value = this.formatcurrencypipe.transform(value);
}
@HostListener('keydown', ['$event']) onKeyDown(event) {
let e = <KeyboardEvent> event;
console.log('e.keyCode: ', e.keyCode, e.ctrlKey, e.metaKey);
//delete, backspace, tab, escape, enter, decimal, period, arrow left, arrow right
if ([46, 8, 9, 27, 13, 110, 190, 37, 39].indexOf(e.keyCode) !== -1
|| (e.keyCode === 65 && (e.ctrlKey || e.metaKey)) //CTRL + A
|| (e.keyCode === 67 && (e.ctrlKey || e.metaKey)) //CTRL + C
|| (e.keyCode === 86 && (e.ctrlKey || e.metaKey)) //CTRL + V
|| (e.keyCode === 88 && (e.ctrlKey || e.metaKey))) { //CTRL + X
//do nothing
return;
}
// Check for number
if ((e.shiftKey || (e.keyCode < 48 || e.keyCode > 57)) && (e.keyCode < 96 || e.keyCode > 105)) {
e.preventDefault();
}
}
}
I've added the stackblitz here: https://stackblitz.com/edit/angular-tys9cy 我在这里添加了stackblitz: https ://stackblitz.com/edit/angular-tys9cy
Reactive form instances like FormGroup
and FormControl
have a valueChanges
method that returns an observable
that emits the latest values. 诸如FormGroup
和FormControl
类的反应性表单实例具有valueChanges
方法,该方法返回observable
并发出最新值的方法。 It does not emit a DOM event. 它不会发出DOM事件。
Solution 解
Instead of valueChange
bind to ngModelChange
that will be triggered on both events ie when formControl is updated in View or via Model. 绑定到ngModelChange
而不是valueChange
,这将在两个事件(即在View中或通过Model更新formControl)时触发。
@HostListener("ngModelChange", [ "$event"]) onNgModelChange(value) {
console.log(value)
this.elementRef.nativeElement.value = this.formatcurrencypipe.transform(value);
}
Based on @vikas answer, I modified so that it only updates with ngModelChange
when the value is dynamically set and not also when the user is editing (as ngModelChange
is too inclusive for what I need): 基于@vikas的答案,我进行了修改,以便在动态设置值时仅使用ngModelChange
进行更新,而在用户进行编辑时则不会进行更新(因为ngModelChange
太包含我所需要的内容):
@HostListener("ngModelChange", [ "$event"]) onNgModelChange(value) {
//when value changes dynamically
if (this.elementRef.nativeElement.dataset.isfocused == 'false') {
console.log('is not focused');
this.elementRef.nativeElement.value = this.formatcurrencypipe.transform(value);
} else {
console.log('is focused');
}
}
@HostListener("focus",["$event.target.value","$event"]) onFocus(value,event) {
this.elementRef.nativeElement.dataset.isfocused = true;
console.log('isfocused: ', this.elementRef.nativeElement.dataset);
this.elementRef.nativeElement.value = this.formatcurrencypipe.parse(value);
if(event.which == 9)
{
return false;
}
this.elementRef.nativeElement.select();
}
@HostListener("blur", ["$event.target.value"]) onBlur(value) {
this.elementRef.nativeElement.dataset.isfocused = false;
this.elementRef.nativeElement.value = this.formatcurrencypipe.transform(value);
}
And the input: 和输入:
<input appCurrency data-isfocused="false" type="text" class="form-control number" formControlName="myInput" />
It seems horridly un-angular to use a data-attribute :-( 似乎很难使用数据属性:-(
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.