Search code examples
angularangular2-formsangular2-directivesangular-directive

Angular 7 reactive forms binding intercepting


I want to format data (provided by user )to my own format or change them on the fly (eg. set 0 when user put a value lower than 0 or something like that). I mostly use a reactive forms solution to connect view with code behind. What I've done it by intercepting my binding between the variable of FormControl type and the control on the view thanks to a directive. I would like to stay with this but the problem is that the directive isn't real interceptor as a value change event occurs with wrong value and then is formatted by directive function (the change event is called second time). This is how I achieved that:

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

Is there a way to achieve the real interception behaviour through directives?

EDIT: I've created a simple sample of my case. Please, take a look. What I want to achieve is only one (second) change event call.

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


Solution

  • So, directive won't help you here, but, you can use that fact that valueChanges is Observable and make a clean and nice solution based on that. Basically you can use map + tap operators to map your changes and set them back to input before subscription. Example:

    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);
    });
    

    Working stackblitz example. Hope that helps.