0

I am trying to make a custom validation so i have created the following directive:

import {Directive, Input} from '@angular/core';
import {AbstractControl, NG_VALIDATORS, Validator} from '@angular/forms';
@Directive({
    selector: '[appEqualValidator]',
    providers: [
        {provide: NG_VALIDATORS, useExisting: EqualValidatorDirective, multi: true}
    ]
})
export class EqualValidatorDirective implements Validator {
    @Input('inputOne')
    inputOne: string;
    @Input('inputTwo')
    inputTwo: string;

    constructor() {
    }

    validate(c: AbstractControl) {

        const value = c.value;
        if ((value == null || value === undefined || value === '') && this.inputOne === this.inputTwo) {
            return {
                equalTo: {condition: this.inputOne === this.inputTwo}
            };
        }
        return null;
    }
}

Now I am trying to add this to my form however I am having some issues using the multiple inputs:

 <div class="form-group">
    <label>E-mail</label>
    <input type="email" class="form-control" placeholder="Indtast email" [(ngModel)]="model.email" name="email" [email]="true" required/>
</div>
<div class="form-group">
    <label style="display: block">Gentag E-mail</label>
    <input type="email" class="form-control" placeholder="Gentag email" [(ngModel)]="model.emailRepeat" required [email]="true" 
[appEqualValidator]="value" name="emailRepeat"/>
    <li *ngIf="!emailVerify">
        De to emails er ikke ens
    </li>
</div>

I am not sure how to use the directive within the form. and making sure i can get both inputs.

I was hoping some of you could point me in the right direction.

2
  • Have you considered using Reactive Forms? Angular has validators that you can implement without much hassle. See here: angular.io/guide/form-validation Commented Oct 30, 2018 at 21:20
  • @IvanS95 Does this have an equal to where you can match two input fields? Commented Oct 30, 2018 at 21:44

2 Answers 2

3

I did something similar with reactive forms.

Here is the validator:

function emailMatcher(c: AbstractControl): { [key: string]: boolean } | null {
  const emailControl = c.get('email');
  const confirmControl = c.get('confirmEmail');

  if (emailControl.pristine || confirmControl.pristine) {
    return null;
  }

  if (emailControl.value === confirmControl.value) {
    return null;
  }
  return { 'match': true };
}

Here is the formbuilder:

this.customerForm = this.fb.group({
  firstName: ['', [Validators.required, Validators.minLength(3)]],
  lastName: ['', [Validators.required, Validators.maxLength(50)]],
  emailGroup: this.fb.group({
    email: ['', [Validators.required, Validators.email]],
    confirmEmail: ['', Validators.required],
  }, { validator: emailMatcher }),
  phone: ''
});

Here is the HTML:

<div class="form-group row">
  <label class="col-md-2 col-form-label"
         for="emailId">Email</label>
  <div class="col-md-8">
    <input class="form-control"
           id="emailId"
           type="email"
           placeholder="Email (required)"
           formControlName="email"
           [ngClass]="{'is-invalid': customerForm.get('emailGroup').errors ||
                                      ((customerForm.get('emailGroup.email').touched || 
                                      customerForm.get('emailGroup.email').dirty) && 
                                      !customerForm.get('emailGroup.email').valid) }" />
    <span class="invalid-feedback">
      <span *ngIf="customerForm.get('emailGroup.email').errors?.required">
        Please enter your email address.
      </span>
      <span *ngIf="customerForm.get('emailGroup.email').errors?.email">
        Please enter a valid email address.
      </span>
    </span>
  </div>
</div>

<div class="form-group row">
  <label class="col-md-2 col-form-label"
         for="confirmEmailId">Confirm Email</label>
  <div class="col-md-8">
    <input class="form-control"
           id="confirmEmailId"
           type="email"
           placeholder="Confirm Email (required)"
           formControlName="confirmEmail"
           [ngClass]="{'is-invalid': customerForm.get('emailGroup').errors ||
                                     ((customerForm.get('emailGroup.confirmEmail').touched || 
                                      customerForm.get('emailGroup.confirmEmail').dirty) && 
                                      !customerForm.get('emailGroup.confirmEmail').valid) }" />
    <span class="invalid-feedback">
      <span *ngIf="customerForm.get('emailGroup.confirmEmail').errors?.required">
        Please confirm your email address.
      </span>
      <span *ngIf="customerForm.get('emailGroup').errors?.match">
        The confirmation does not match the email address.
      </span>
    </span>
  </div>
</div>

You can find the complete solution here:

https://github.com/DeborahK/Angular-ReactiveForms/tree/master/Demo-Final-Updated/src/app/customers

Sign up to request clarification or add additional context in comments.

Comments

1

You can do this wrapping both inputs in an NgModelGroup. It extends AbstractControlDirective, so it may take validators.

<div ngModelGroup="emails" #emails="ngModelGroup" [appEqualValidator]="value">
    <div class="form-group">
        <label>E-mail</label>
        <input type="email" class="form-control" placeholder="Indtast email" [(ngModel)]="model.email" name="email" [email]="true" required/>
    </div>
    <div class="form-group">
        <label style="display: block">Gentag E-mail</label>
        <input type="email" class="form-control" placeholder="Gentag email" [(ngModel)]="model.emailRepeat" required [email]="true" name="emailRepeat"/>
        <li *ngIf="!emailVerify">De to emails er ikke ens</li>
    </div>
</div>

Whenever a child control changes, the group validator will be called. In validate(), you will need to cast to a FormGroup and input value equality.

Read More Here

1 Comment

Hey mate when i try this i get : Can't bind to 'appEqualValidator' since it isn't a known property of 'div'

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.