Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular: updateValueAndValidity from directive

I have a directive that appends decimals, if the input value is a whole number, on blur. Below is the implementation.

import { Directive, ElementRef, Input, OnInit, HostListener, forwardRef } from '@angular/core';
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';

@Directive({
  selector: '[price]',
  providers: [
    {
      provide: NG_VALUE_ACCESSOR,
      useExisting: forwardRef(() => PriceDirective),
      multi: true
    }
  ]
})
export class PriceDirective implements ControlValueAccessor {

  constructor(private el: ElementRef) { }

  // ControlValueAccessor interface
  private _onChange = (_) => { };
  private _onTouched = () => { };

  @HostListener('blur', ['$event'])
  input(event) {
    !!event.target.value ? $(this.el.nativeElement).val(Number(event.target.value).toFixed(2)) : $(this.el.nativeElement).val(null);

    this._onChange(parseFloat(event.target.value));
    this._onTouched();
  }
  writeValue(value: any): void {
    !!value ? $(this.el.nativeElement).val(Number(value).toFixed(2)) : $(this.el.nativeElement).val(null);
  }

  registerOnChange(fn: (_: any) => void): void { this._onChange = fn; }
  registerOnTouched(fn: any): void { this._onTouched = fn; }

}

Things work as expected.

But, since Angular doesn't trigger validation when the value is changed programatically, the textbox that has this directive, is not validated.

How can I enable validation in this case, by other means than passing the control reference as an input to the directive and calling updateValueAndValidity on it, or calling updateValueAndValidity on input or blur.

It would be great if someone suggests me a way to trigger validation from the directive itself.

like image 608
karthikaruna Avatar asked Jan 27 '18 05:01

karthikaruna


1 Answers

I solved the same problem in this way. It is my first approach.

  update() {

    // ...

    const el = this.el.nativeElement;
    const reg = new RegExp(this.textMaskConfig.replacement);

    el.value = this.prevStr.replace(reg, this.currentChar);

    // ...

  }

But It doesn't fire the validate event. So I get the NgControl component and used setValue() method.

  constructor(private el: ElementRef, private ctrl: NgControl) {   
  }

  @HostListener('keydown', ['$event']) onKeyDownHandler(e) {
    this.ctrl.control.setValue(value);
  }
like image 79
seflix Avatar answered Oct 13 '22 20:10

seflix