I'm trying to inject my users service into my validator constraint interface but it doesn't seem to work:
import { ValidatorConstraintInterface, ValidatorConstraint, ValidationArguments, registerDecorator, ValidationOptions } from "class-validator";
import { UsersService } from './users.service';
@ValidatorConstraint({ async: true })
export class IsEmailAlreadyInUseConstraint implements ValidatorConstraintInterface {
constructor(private usersService: UsersService) {
console.log(this.usersService);
}
validate(email: any, args: ValidationArguments) {
return this.usersService.findUserByEmail(email).then(user => {
if (user) return false;
return true;
});
return false;
}
}
But, as usersService is logged null, I can't access its methods.
Any insight on this matter?
For those who might be suffering from this issue:
class-validator requires you to use service containers if you want to inject dependencies into your custom validator constraint classes. From: https://github.com/typestack/class-validator#using-service-container
import {useContainer, Validator} from "class-validator";
// do this somewhere in the global application level:
useContainer(Container);
So that we need to add the user container function into the global application level.
1. Add the following code to your main.ts bootstrap function after app declaration:
async function bootstrap() {
const app = await NestFactory.create(AppModule);
useContainer(app.select(AppModule), { fallbackOnErrors: true });
...}
The {fallbackOnErrors: true} is required, because Nest throw Exception when DI doesn't have required class.
2. Add Injectable() to your constraint:
import {ValidatorConstraint, ValidatorConstraintInterface} from 'class-validator';
import {UsersService} from './user.service';
import {Injectable} from '@nestjs/common';
@ValidatorConstraint({ name: 'isUserAlreadyExist', async: true })
@Injectable() // this is needed in order to the class be injected into the module
export class IsUserAlreadyExist implements ValidatorConstraintInterface {
constructor(protected readonly usersService: UsersService) {}
async validate(text: string) {
const user = await this.usersService.findOne({
email: text
});
return !user;
}
}
3. Inject the constraint into your module as a provider and make sure that the service you intend to inject into your constraint are also available to a module level:
import {Module} from '@nestjs/common';
import { UsersController } from './user.controller';
import { UsersService } from './user.service';
import { IsUserAlreadyExist } from './user.validator';
@Module({
controllers: [UsersController],
providers: [IsUserAlreadyExist, UsersService],
imports: [],
exports: []
})
export class UserModule {
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With