Search code examples
angularangular-material-tableangular-custom-validatorsmat-form-field

custom validator in angular4 material table results error


I am using angular4-material-table . there I tried to add custom input validation I have created seperate validator service there I called custom function to hit my api based on api result it will throws input valid or not.

here is my code can anyone suggest me what mistake I made,

import { Injectable } from '@angular/core';
import { FormGroup, FormControl, Validators } from '@angular/forms';
import { ValidatorService } from 'angular4-material-table';
import { AbstractControl } from '@angular/forms';
import { ApiCallService } from 'api.service';

    @Injectable()
    export class MatTableValidatorService implements ValidatorService {
        constructor( private api_call: ApiCallService) {  
        }
       getRowValidator(): FormGroup {
        return new FormGroup({
          'name': new FormControl(null, [Validators.required, this.nameValidator]),
          });
      }
        nameValidator(control: AbstractControl): { [key: string]: boolean } | null {
            this.api_call
            .api_function(parameter)
            .subscribe(data => {
              const arrayVal = data.response;
              if(arrayVal.length > 0)
              {
                return {'dnsCheck': true}
              }
              return null;
          });
            return null;
        }

    }

this one returns error : cannot read property of api_call even though I declared it in constructor

and another way:

   public nameValidator = (control: AbstractControl) => {
         this.api_call
            .api_function(parameter)
            .subscribe(data => {
              const arrayVal = data.response;
              if(arrayVal.length > 0)
              {
                return {'dnsCheck': true}
              }
              return null;
          });
        };

this way works but even though input valid or not it always throws error. I have checked output with console seems getting from api is perfectly done. can anyone assist me whats my mistake. Thanks in advance.

A stackblitz example can be seen here.


Solution

  • I am not sure whether it is a reason, however you are not awaiting result of your api call. Your code always return null. So we need to await result of API call:

    async nameValidator(control: AbstractControl): { [key: string]: boolean } | null {  
        const result = await this.api_call.api_function(parameter);
        const arrayVal = result.response;
    
        if (arrayVal.length > 0)
              return {'dnsCheck': true}
    
        return null;
    }
    

    UPDATE:

    You can add custom validator. Forbidden name is Mark, if you write forbidden name, then input will not save this value:

    @Injectable()
    export class PersonValidatorService implements ValidatorService {
      getRowValidator(): FormGroup {
        return new FormGroup({
          'name': new FormControl(null, [Validators.required, forbiddenNameValidator()])
    
          });
      }
    }
    
    export function forbiddenNameValidator(): ValidatorFn {
      return (control: AbstractControl): {[key: string]: any} | null => {    
        const forbidden =  'Mark';
        console.log(`forbidden name is `, forbidden);
        return (forbidden == control.value) ? {'forbiddenName': {value: control.value}} : null;
      };
    }
    

    An example can be seen here.