I tried to solve this problem by:
S1: Create a custom validator @IsDeliveryCodeValid() to verify the delivery_code
and add the needAddress
value to the DTO
S2: Use @ValidateIf() to check whether the address needs to be validated based on the needAddress
value or not
is-delivery-code-valid.validator.ts
import {
ValidatorConstraint,
ValidatorConstraintInterface,
ValidationArguments,
registerDecorator,
ValidationOptions,
} from 'class-validator';
import { Injectable } from '@nestjs/common';
import { DeliveryService } from './delivery.service';
@ValidatorConstraint({ async: true })
@Injectable()
export class IsDeliveryCodeValidConstraint
implements ValidatorConstraintInterface
{
constructor(private readonly deliveryService: DeliveryService) {}
async validate(code: string, args: ValidationArguments): Promise<boolean> {
const dto = args.object as any;
const deliveryType = await this.deliveryService.getDeliveryTypeByCode(code);
if (deliveryType) {
dto.needAddress = deliveryType.needAddress;
return true;
}
return false;
}
defaultMessage(): string {
return 'Invalid delivery code!';
}
}
export function IsDeliveryCodeValid(validationOptions?: ValidationOptions) {
return function (object: Object, propertyName: string) {
registerDecorator({
target: object.constructor,
propertyName,
options: validationOptions,
constraints: [],
validator: IsDeliveryCodeValidConstraint,
});
};
}
create-order.dto.ts
import {
ValidateIf,
ValidateNested,
IsNotEmptyObject,
} from 'class-validator';
import { Type } from 'class-transformer';
import { CreateOrderAddressDTO } from './create-order-address.dto';
import { IsDeliveryCodeValid } from './is-delivery-code-valid.validator';
export class CreateOrderDTO {
@IsDeliveryCodeValid({ message: 'Invalid delivery code' })
delivery_code: string;
@ValidateIf((o) => o.needAddress)
@IsNotEmptyObject({ message: 'Address is required' })
@ValidateNested()
@Type(() => CreateOrderAddressDTO)
address: CreateOrderAddressDTO;
needAddress?: boolean; // This field is dynamically attached by IsDeliveryCodeValid validator
}