I'm trying to use class-validator
to create a dynamic validation of person data based on user's selected fields.
E.g:
// I have the following class/type
class PersonType {
name = ''
email = ''
phone = ''
motherName = ''
... etc
}
....
// And the user selected these fields as required fields:
['name', 'motherName']
Reading class-validator
docs I've found conditional validation but this only shows how to use class's props as validation parameter:
import { ValidateIf, IsNotEmpty } from 'class-validator'
class PersonValidator {
@ValidateIf(o => o.CLASS_PROP .... condition )
@IsNotEmpty()
name: string
.... rest
}
My validation function is this right now:
import { validate } from 'class-validator'
import { plainToInstance } from 'class-transformer'
async function isClassValid(C: any, O: any) {
const object = plainToInstance(C, O)
const errors = await validate( object )
if( errors.length > 0 ) throw Error('Class not valid')
return true
}
...
app.post('/person', async (req: Request, res: Response) => {
const {body} = req
const requiredFields = await getFromDatabase(...) // returns ['name', 'motherName']
try {
await isClassValid( PersonValidator, body )
// continue
} catch( error ) {
// handle error
}
})
How can I validate class's fields based on requiredFields
fields array?
What I want to achieve is:
class PersonValidator {
@ValidateIf(() => requiredFields.includes[ 'name' ])
@IsNotEmpty()
name: string
.... rest
}
You can return validator class with decorators with a function:
function getPersonValidator(
requiredFields: RequiredFieldsType
): typeof PersonType {
class PersonValidator {
@( requiredFields.includes[ 'name' ] ? IsNotEmpty : IsOptional )()
name: string
@( requiredFields.includes[ 'email' ] ? IsEmail : IsOptional )()
email: string
etc ...
}
return PersonValidator
}
Then call it in your route:
const requiredFields = ['name', 'motherName']
try {
await isClassValid( getPersonValidator( requiredFields ), body )
// continue
} catch( error ) {
// handle error
}
Hope this helps :)