Lift validation directive from input to parent div

36 Views Asked by At

I have the following input

<div>
  <input
    type="text"
    name="name"
    [(ngModel)]="query.name"
    [appInvalidName]="query.format"
    (update)="onUpdate()"
    #name="ngModel"
    placeholder="Enter name..."
  />
  <div class="error-message" *ngIf="name.invalid">
    <span>{{name.errors?.["message"]}}</span>
  </div>
</div>

where I can enter a name (query.name) which is then validated depending on query.format. I would like to make the whole div into a component TextInputComponent, thus appInvalidName needs to be passed from the outer div down to my input, as well as ngModeland update

<app-text-input
  [appInvalidName]="query.format"
  [(ngModel)]="query.name"
  (update)="onUpdate()"
/>

That's the definition of the directive:

import {
  AbstractControl,
  NG_VALIDATORS,
  ValidationErrors,
} from '@angular/forms';
import { Directive, EventEmitter, Input, Output } from '@angular/core';
import { Format } from './app.component';

@Directive({
  selector: '[appInvalidName]',
  providers: [
    {
      multi: true,
      provide: NG_VALIDATORS,
      useExisting: InvalidNameDirective,
    },
  ],
})
export class InvalidNameDirective {
  @Input('appInvalidName') format?: Format;
  @Output() update = new EventEmitter();

  ngOnChanges(): void {
    this.update.emit();
  }

  validate(control: AbstractControl): ValidationErrors | null {
    if (this.format === 'short' && !/\w\.\w/.test(control.value)) {
      return {
        message: 'wrong format',
      };
    }

    return null;
  }
}

StackBlitz

0

There are 0 best solutions below