yashhy
yashhy

Reputation: 3096

component vs directive event priority

I have written a directive which accepts only numbers implementing ControlValueAccessor.

onBlur of that particular element I would update its model like below.

@HostListener('blur',['$event']) onBlur(event) {
    this.directiveModel = this.getOnlyNumberLogic();
    this.propagateChange(this.directiveModel); <-- update model
    this.renderer.setElementProperty(this.el.nativeElement, 'value', this.directiveModel);
  }

The above logic works perfectly, but the problem comes when I add (blur) on the component element's HTML like below:

<input type="text" name="number"
    #numberId="ngModel"
    required
    [(ngModel)]="obj.number"
    pattern="^\d{11}(?:\d{5})?$"
    numberOnly   <---- Directive
    (blur)="numberId.valid && onNumberBlur(numberId.value)"
    maxlength="16"/>

Every single time the component's (blur) executes first and then directive's @HostListener('blur'), because of which the [(ngModel)] isn't updating as the this.propagateChange() is inside the directive's blur is called later.

Question:

Is there anyway to set a priority that directive's blur should execute first?

Upvotes: 2

Views: 1119

Answers (1)

yashhy
yashhy

Reputation: 3096

I solved the above problem with EventEmitter. I have one EventEmitter for the directive :

@Output() onDirectiveBlur = new EventEmitter();

Then on directive's blur I would emit this event,

@HostListener('blur',['$event']) onBlur(event) {
  this.directiveModel = this.getOnlyNumberLogic();
  this.propagateChange(this.directiveModel); <-- update model
  this.renderer.setElementProperty(this.el.nativeElement, 'value', this.directiveModel);
  this.onDirectiveBlur.emit();
}

which is bind with the element in the component's HTML, like below:

 <input type="text" name="number"
    #numberId="ngModel"
    required
    [(ngModel)]="obj.number"
    pattern="^\d{11}(?:\d{5})?$"
    numberOnly   <---- Directive
    (onDirectiveBlur)="numberId.valid && onNumberBlur(numberId.value)"
    maxlength="16"/>

with this case the component's (custom) blur will only call after directive's blur and guarantees the model will always be updated.

I'm not accepting this as answer (for now) because I feel there would be some better way than including event onDirectiveBlur, let me know your thoughts.

Upvotes: 1

Related Questions