0

I'm trying to use the output from a custom validation directive in one element <input> to control the display of another element <p>, but can't figure out how to make it work. This is what I have so far:

Custom Directive (no-special-chars-directive.ts)

import { Directive } from '@angular/core';
import { Validator, 
        FormControl, 
        NG_VALIDATORS, 
        ValidationErrors} from "@angular/forms";

@Directive({
  selector: '[appNoSpecialChars]',
  providers: [{provide: NG_VALIDATORS, useExisting: NoSpecialCharsDirective, multi: true}],
  exportAs: 'noSpecChars'
})
export class NoSpecialCharsDirective implements Validator{

  constructor() { }
  validate(c: FormControl): ValidationErrors {
    //console.log("input value: " + c.value);
    const hasSpecialChars = /[~!@#\^&*+=\-\[\]\';,/{}|\":<>\?\\()]/.test(c.value);
    const message = {
      'hasSpecialChars' : {
        'message': 'No Special Chars Allowed'
      }
    };
    return hasSpecialChars ? message : null;
  }
}

Here is the template: (git-search.component.html)

<h3>{{title}} - {{displayQuery}} -- (version: Template Driven)</h3>
<form #myForm="ngForm" (ngSubmit)="sendQuery()">
  <div *ngFor="let key of modelKeys">
      {{key}} 
      <input  #myInput name="{{key}}" placeholder="Enter {{key}} Here" [(ngModel)]="model[key]" required *ngIf="key==='q'" appNoSpecialChars/>
      <input  #myInput name="{{key}}" placeholder="Enter {{key}} Here" [(ngModel)]="model[key]" minlength = '2' maxlength='4' *ngIf="key==='stars'" appNoSpecialChars />      
      <input  #myInput name="{{key}}" placeholder="Enter {{key}} Here" [(ngModel)]="model[key]" *ngIf="key!=='q' && key!=='stars'" appNoSpecialChars/> 
      <p *ngIf="!myForm[key].valid" >Not valid</p> 
  </div>
  <button type="submit" [disabled]="!myForm.valid">Submit</button> 
</form>

I want the <p> element to optionally display whenever there is invalid input in the preceding <input>. I've tried multiple permutations for the *ngIf statement and in the inputs themselves, but haven't found anything that works yet. Everything worked fine before I started playing around with the optional display of the <p> element. Any ideas?

Crowdpleasr
  • 3,574
  • 4
  • 21
  • 37

1 Answers1

1

Change the line

<p *ngIf="!myForm[key].valid" >Not valid</p>

to

<p *ngIf="!myForm.form.get(key)?.valid" >Not valid</p> 

myForm.form gets the default/in your case only FormGroup which holds all FormControls.

The ? is like a special null coalesce operator (Why we use "?" operator in template binding in angular 2) which prevents errors in case myForm.form.get(key) is NULL.

you can see it in action here https://stackblitz.com/edit/angular-liqgux

Arikael
  • 1,989
  • 1
  • 23
  • 60
  • Quick follow up question . . . How would I access the value returned from the directive, from outside of the element hosting the directive? Also, from inside the element hosting the directive? – Crowdpleasr Mar 08 '19 at 20:52
  • I don't know from the top of my hat but you should ask this as another/seperate question. – Arikael Mar 08 '19 at 20:58