New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
question: <Advanced conditional validation> #2467
Comments
Hello, We had similar need for the application we develop and we created custom validators to manage those cases:
For the case you show it would be: export class CreateItemDto {
@IsBoolean()
price_show: boolean;
@IsOptionalIf<CreateItemDto>(o => o.price_show === false)
@IsEmptyIf<CreateItemDto>(o => o.price_show === false)
@IsNotEmptyIf<CreateItemDto>(o => o.price_show === true)
@IsNumber()
@Min(10)
//TODO: if price_show is false, then price MUST BE NULL. How to achieve that?
price: number | null;
} It is a bit heavy but it works fine! The custom validatorsimport { isEmpty, registerDecorator, ValidationArguments, ValidationOptions } from 'class-validator';
export function IsEmptyIf<T>(condition: (object: T) => boolean, validationOptions?: ValidationOptions) {
return function (object: Object, propertyName: string) {
registerDecorator({
name: 'isEmpty',
target: object.constructor,
propertyName: propertyName,
constraints: [condition],
options: validationOptions,
validator: {
validate(value: any, args: ValidationArguments) {
const [relatedCondition] = args.constraints;
const cond = relatedCondition(args.object);
if (cond && Array.isArray(value) && validationOptions && validationOptions.each)
return value.every(v => isEmpty(v));
else if (cond)
return isEmpty(value);
return true;
}
}
});
};
} // eslint-disable-next-line no-restricted-imports
import { isNotEmpty, registerDecorator, ValidationArguments, ValidationOptions } from 'class-validator';
export function IsNotEmptyIf<T>(condition: (object: T) => boolean, validationOptions?: ValidationOptions) {
return function (object: Object, propertyName: string) {
registerDecorator({
name: 'isNotEmpty',
target: object.constructor,
propertyName: propertyName,
constraints: [condition],
options: validationOptions,
validator: {
validate(value: any, args: ValidationArguments) {
const [relatedCondition] = args.constraints;
const cond = relatedCondition(args.object);
if (cond)
return isNotEmpty(value);
return true;
}
}
});
};
} import { ValidateIf, ValidationOptions } from 'class-validator';
/**
* Checks if value is missing and if so, ignores all validators.
**/
export function IsOptionalIf<T>(condition: (object: T, value: any) => boolean, validationOptions?: ValidationOptions) {
return ValidateIf((object: T, value: any) => {
const valueIsNil = (value === '' || value === null || value === undefined);
return !valueIsNil || !condition(object, value);
}, validationOptions);
} If you find a better way, I would be interested. Indeed we would have loved to have a single validator to merge the 3 validator as we often use them together... |
Thanks for your reply BUONJG! Someone helped me on stackoverflow a couple days ago. Anyway, validating more complex data is strange in this library... |
How to make more advanced conditional validation?
Look at the example:
The problem:
If
price_show
varriable isfalse
all decorators are ignored andprice
can be any value.Is there possibility to make something like 'else' statement to pass different decorators?
https://github.com/typestack/class-validator#conditional-validation
The text was updated successfully, but these errors were encountered: