alim1990
alim1990

Reputation: 4972

Angular 6 transforming a custom validator function into a class giving undefined function error

I have created this custom validator to check if an email does end with a specific domain:

import { AbstractControl } from '@angular/forms';
import { stringify } from '@angular/compiler/src/util';

export function validateEmailDomain(control: AbstractControl)
    {

        if(!stringify(control.value).endsWith('test.com'))
        {
            return {response: true};
        }
        return null;
    }
}

Then I applied it to the specific contorl of a reactive formGroup:

'email': new FormControl('', [Validators.email, validateEmailDomain]),

This script works well. But, I have a global variable service, where I add all my variables used around my project so when I sell it to an organization or a company, I just change few variables like logo image, icon, title and the domain of the email server, instead of going to each component and change it manually.

So I need to pass the global variable service to the custom validators, and check the control value if it does match or not.

After few searches on stack overflow, I read that I should transform the export function into a class, so I did the following:

import { AbstractControl } from '@angular/forms';
import { stringify } from '@angular/compiler/src/util';
import { GlobalVarService } from 'src/app/global-var.service';

export class emailDomain{
    constructor(private globalVar: GlobalVarService){}
    static validateEmailDomain(control: AbstractControl) {

        if (!stringify(control.value).endsWith(this.globalVar.emailDomain)) {
            return { response: true };
        }
        return null;
    }
}

and at the control:

  'email': new FormControl('', [Validators.email, emailDomain.bind(validateEmailDomain)]),

It didn't work as I got an error of undefined validateEmailDomain at the line above.

Upvotes: 1

Views: 1920

Answers (3)

Kamil Kiełczewski
Kamil Kiełczewski

Reputation: 92327

Instead this:

emailDomain.bind(validateEmailDomain)

use this

emailDomain.bind(emailDomain.validateEmailDomain)

Answer to antoher question from commnent (error: Property 'globalVar' does not exist on type 'typeof emailDomain'):

You canot use dynamic class field (globalVar) inside static method. So may be try to pass this value as static method parameter e.g. (i wrtie code from head so test it)

// I assume that you have this.globalVar here (so no in emailDomain constructor, but in place where you use that class), and also you have control: FormCotnrol object

'email': new FormControl('', [
    Validators.email, 
    emailDomain.bind( () => emailDomain.validateEmailDomain(control , this.globalVar) )
])

Ofcourse you need to change emailDomain.validateEmailDomai to use this parameter

Upvotes: 1

Yousef khan
Yousef khan

Reputation: 3204

I would have done this in following way.

Declare one variable

validateEmailDomain: any;
//add service in the same component
constructor(private globalVar: GlobalVarService){}
// then in ngOnInit initialize your var
ngOnInit(): void {
    this.validateEmailDomain = (control: FormControl) => {
      // you have the control here and you can call any exported method like validateEmailDomain(control: AbstractControl, globalVar: GlobalVarService)

      if (!stringify(control.value).endsWith(this.globalVar.emailDomain)) {
          return { response: true };
      }
      return null;
  };
}

then use it like

'email': new FormControl('', [Validators.email, this.validateEmailDomain]),

Let me know if I have missed anything

Update

export function validateEmailDomain(control: AbstractControl, globalVar: GlobalVarService) {
// your validations
}

And then use this method like

this.validateEmailDomain = (control: FormControl) => {
  return validateEmailDomain(control, this.globalVar);
};

Upvotes: 1

ibenjelloun
ibenjelloun

Reputation: 7723

You could make your validator more generic :

export function validateEmailDomain(globalVar) {
 return function (control) {
    if(!stringify(control.value)
        .endsWith(globalVar.emailDomain))
    {
     return {response: true};
    }
    return null;
   };
}

Then when you use it just pass the global vars :

'email': new FormControl('', 
 [Validators.email, validateEmailDomain(this.globalVar)]),

Upvotes: 1

Related Questions