bat7
bat7

Reputation: 866

Angular 6 template driven form add custom validation with condition

I am using template driven form in angular 6.

I added a custom validation named identityNumberValidator for identity number field that check if user typed correct identity number (IL identity)

The validation directive looks as bellow:

@Directive({
    selector: '[identityNumberValidator]',
    providers: [
        {
            provide: NG_VALIDATORS,
            useExisting: IdentityNumberValidator,
            multi: true
        }
    ]
})
export class IdentityNumberValidator implements Validator {
    validator: ValidatorFn;

    constructor() {
        this.validator = this.identityNumberValidator();
    }

    validate(c: FormControl) {
        return this.validator(c);
    }


    identityNumberValidator(): ValidatorFn {
        return (c: FormControl) => {
            let isValid = true;
            if (c.value && c.value.length >= 9) {
                let idNum = c.value.padStart(9, '0');
                // CHECK THE ID NUMBER algoritm - http://halemo.net/info/idcard/
                let mone = 0;
                for (let i = 0; i < 9; i++) {
                    var incNum = idNum[i];
                    incNum *= (i % 2) + 1;
                    if (incNum > 9)
                        incNum -= 9;
                    mone += incNum;
                }
                if (mone % 10 !== 0) {
                    isValid = false;
                }
                else {
                    isValid = true;
                }
            }

            if (isValid == true) {
                return null;
            } else {
                return {
                    identityNumberValidator: {
                        valid: false
                    }
                };
            }
        }
    }

I Use it in my component for input element here:

<mat-form-field appearance="outline">
            <mat-label>מספר מזהה</mat-label>
            <input matInput
                   maxlength="9"
                   minlength="9"
                   required
                   identityNumberValidator
                   #identityNumberField="ngModel"
                   [(ngModel)]="identityNumber"
                   name="identityNumberField" />
            <mat-error *ngIf="identityNumberField.errors?.required">
              {{ eMessages.required}}
            </mat-error>
            <mat-error *ngIf="identityNumberField.errors?.minlength">
              יש להזין 9 ספרות
            </mat-error>
            <mat-error *ngIf="identityNumberField.errors?.identityNumberValidator">
              מספר זהות שגוי
            </mat-error>
          </mat-form-field>

My question is how can I use this validation with condition on other element?

I tried [identityNumberValidator] = "element == 1 ? '' : null" but does not work. I read this post Angular conditional validation on template driven form

but both [attr.identityNumberValidator] and [class.identityNumberValidator] does not work. The validation does not appear at all.

I know I can use reactive form but I do not want to.

So I can use two different input elements and use *ngIf between them but I want to find a solution to use only one element.

Any Idea?

Upvotes: 1

Views: 2559

Answers (1)

Ushmi Dave
Ushmi Dave

Reputation: 286

You can bind you custom function in the template driven approach, but that can be possible through @rxweb/reactive-form-validators.

Here, I have used [compose] attribute on input filed where I have passed the validator method and set conditional expression. See the code below:

[compose]="{validators:[identityNumberValidator.bind(this)],'conditionalExpression':'x => x.userName == \'Bharat\''}"

Here is the complete HTML. where I have defined two control, 'userName' and 'firstName' the firstname validation will be fired once the 'userName' control value is 'Bharat'. See the below HTML code snippet.

    <div>
      <form #userinfoForm = "ngForm" [rxwebForm]="userinfoForm" [model]="userinfo">
         <div class="form-group">
          <label>User Name</label>
    	    <input type="text" name="userName" [(ngModel)]="userinfo.userName"  class="form-control" />
    
    	  
        </div>
        <div class="form-group">
          <label>First Name</label>
    	    <input type="text" name="firstName" [(ngModel)]="userinfo.firstName"  class="form-control" [compose]="{validators:[identityNumberValidator.bind(this)],'conditionalExpression':'x => x.userName == \'Bharat\''}"/>
    
    	
        </div>
        <button [disabled]="!userinfoForm.valid" class="btn btn-primary">Submit</button>
      </form>
    </div>

Here is the control custom method:

   identityNumberValidator =  (c: FormControl) => {
       
          let a = this;
          return {"msg":""};
        }

Stackbliz Example

Upvotes: 0

Related Questions