user16750862
user16750862

Reputation: 31

Two validators for one single entity in DTO

Are there any ways or would it be possible to have two validator in one single entity? Like for the given example code below, the identifier would accept an email as its payload but it would also accept number/mobile number as its payload as well.

  @ApiProperty()
  @IsString()
  @IsNotEmpty()
  @IsEmail()
  identifier: string;

EDIT:

I have tried,

  @ApiProperty()
  @IsString()
  @IsNotEmpty()
  @IsEmail()
  @IsPhoneNumber('US')
  identifier: string;

But it does not work.

EDIT 2: I found a reference code based on this previous thread, How to use else condition in validationif decorator nestjs class-validator?, and I copied his validation class.

import { ValidatorConstraint, ValidatorConstraintInterface, ValidationArguments } from "class-validator";
import { IdentifierType } from "../interface/access.interface";

@ValidatorConstraint({ name: 'IdentifierValidation', async: false })
export class IdentifierValidation implements ValidatorConstraintInterface {
    validate(identifier: string, args: ValidationArguments) {

        if (JSON.parse(JSON.stringify(args.object)).type === IdentifierType.MOBILE) {

            var regexp = new RegExp('/^[\+]?[(]?[0-9]{3}[)]?[-\s\.]?[0-9]{3}[-\s\.]?[0-9]{4,6}$/im');
            // "regexp" variable now validate phone number.
            return regexp.test(identifier);
        } else {
            regexp = new RegExp("^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$");
            // "regexp" variable now validate email address.
            return regexp.test(identifier);
        }

    }

    defaultMessage(args: ValidationArguments) {

        if (JSON.parse(JSON.stringify(args.object)).type === IdentifierType.MOBILE) {
            return 'Enter a valid phone number.'
        } else {
            return 'Enter a valid email address.'
        }
    }
}

DTO -

export class VerifyOtpDto {
  @Validate(IdentifierValidation)
  @ApiProperty()
  @IsNotEmpty()
  identifier: string;

  @ApiProperty({ enum: IdentifierType })
  @IsNotEmpty()
  identifierType: IdentifierType;
}

ENUM -

export enum IdentifierType {
  EMAIL = 'email',
  MOBILE = 'mobile',
}

It does work with email but trying to feed a mobile number still does not work.

Upvotes: 1

Views: 2155

Answers (2)

Vahid Najafi
Vahid Najafi

Reputation: 5263

You have two ways to do this, first with regex:

@Matches(/YOUR_REGEX/, {message: 'identifier should be email or phone'})
identifier: string;

Or you can get the idea from this:

@IsType(Array<(val: any) => boolean>)
@IsType([
 val => typeof val == 'string',
 val => typeof val == 'boolean',
])
private readonly foo: boolean | string;

Upvotes: 1

nari120
nari120

Reputation: 128

Of course it can get more than one validator in one DTO column.

Did you check https://www.npmjs.com/package/class-validator here?

if you want to check mobile number, you can use to @IsMobilePhone(locale: string).

Upvotes: 0

Related Questions