Angular 7 反应形式绑定拦截

Angular 7 reactive forms binding intercepting

我想将数据(由用户提供)格式化为我自己的格式或即时更改它们(例如,当用户输入的值低于 0 或类似值时设置为 0)。我主要使用反应式表单解决方案将视图与隐藏代码连接起来。由于指令,我通过拦截 FormControl 类型的变量和视图上的控件之间的绑定来完成它。我想继续这样做,但问题是该指令不是真正的拦截器,因为值更改事件以错误的值发生,然后由指令函数格式化(第二次调用更改事件)。我就是这样实现的:

@HostListener("blur", ["$event.target.value"])onBlur(event: any) {
    let value = this.transformValue(event);
    this.control.setValue(value, { emitEvent: false });
    this.el.value = value;
}

有没有办法通过指令实现真正的拦截行为?

编辑: 我已经为我的案例创建了一个简单示例。请看一下。我想要实现的只是一次(第二次)更改事件调用。

https://stackblitz.com/edit/angular-ctnjup

Jaume,如果指令应用于输入控件,您可以在指令的构造函数中注入 ElementName 和控件本身

constructor(private elementRef: ElementRef,private control:NgControl) {
   //this.control was the control itself
}

因此,您可以添加 HotListener over input、over focus、over blur...

@HostListener("blur", ["$event.target.value"])onBlur(event: any) {
    let value = this.transformValue(event);
    this.control.setValue(value, { emitEvent: false });
    this.el.value = value;
}

所以,指令不会帮助你,但是,你可以使用 valueChangesObservable 的事实并制作 基于此的干净漂亮的解决方案。基本上,您可以使用 map + tap operators 来映射您的更改并将它们设置回输入 before subscription。示例:

this.sub$ = this.formControl.valueChanges.pipe(
  map(x => x === "" ? 0 : parseFloat(x) || 0),
  tap(x => this.formControl.setValue(x, {emitEvent: false}))
).subscribe(x => {
  console.log("change: " + x);
  this.changes.push(x);
});

工作stackblitz example。希望对您有所帮助。