Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Accessing other attribute directives from an attribute directive

I've written a custom validator for Angular2 Forms. It simply compares the input to a blacklist, this works fine so far. With one exception: if the blacklist is updated after form validation is done, the form won't be validated again until the input-field changes. To fix this I'm getting the template variable in my component and trigger an update manually.

@ViewChild('email') emailNgModel: NgModel;
...
this.emailBlacklist = this.emailBlacklist.concat(email);
        let sub = this.zone.onStable.asObservable().subscribe(() => {
          if (sub) sub.unsubscribe();
          this.zone.run(() => {
            this.emailNgModel.control.updateValueAndValidity();
          });
        });

I'd much prefer to listen to changes in my directive and trigger the update from there (see TODO below)

export const BLACKLIST_VALIDATOR: any = {
  provide: NG_VALIDATORS,
  useExisting: forwardRef(() => BlacklistValidatorDirective),
  multi: true
};

@Directive({
  selector: '[validateBlacklist][formControlName],[validateBlacklist][formControl],[validateBlacklist][ngModel]',
  providers: [BLACKLIST_VALIDATOR]
})
export class BlacklistValidatorDirective implements Validator, OnChanges {
  @Input('validateBlacklist') blacklist;

  constructor() {
  }

  ngOnChanges(changes: SimpleChanges): void {
    if ('blacklist' in changes) {
      // TODO trigger ngModel.control.updateValueAndValidity()
    }
  }

  validate(c: AbstractControl): {[p: string]: any} {
    return validateBlacklist(this.blacklist, c.value);
  }

}

export function validateBlacklist(blacklist: string[], value) {
  if (blacklist && blacklist.indexOf(value) >= 0) {
    return {
      blacklist: true
    };
  }
  return null;
}

Now the question is, how can I get ngModel from the host? Or how do I get other directives on the same host in general ?

like image 593
Su-Au Hwang Avatar asked Dec 06 '25 05:12

Su-Au Hwang


1 Answers

Just inject it

constructor(private ngModel:NgModel) {

I'm pretty sure this will do exactly what you want.

like image 72
Günter Zöchbauer Avatar answered Dec 07 '25 21:12

Günter Zöchbauer



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!