I want to get value of type property in class B for validate class A.
Class A is used as a property type for the property a
in Class B.
class Content1 {}
class Content2 {}
class A {
@IsValidContent()
content: Content1 | Content2;
}
class B {
@Type(() => A)
@ValidateNested({ each: true })
a: A;
type: string;
}
export function IsValidContent(validationOptions?: ValidationOptions) {
return (object: Object, propertyName: string) => {
registerDecorator({
name: "isValidContent",
target: object.constructor,
propertyName,
constraints: [],
options: validationOptions,
validator: {
validate(value: any, args: ValidationArguments) {
const type = args.object["type"]; // how to get type properties from parent
switch (type) {
case "X":
return isValidType(value, Content1);
case "Y":
return isValidType(value, Content2);
default:
return false;
}
},
},
});
}
}
How to get type properties from class B in order to validate the property content
in class A?
Validation decorator is IsValidContent
i have the same problem.
I have created a validator that add parent object in each child:
import { Exclude } from 'class-transformer';
import {
Validate,
ValidationArguments,
ValidationOptions,
ValidatorConstraint,
ValidatorConstraintInterface,
} from 'class-validator';
@ValidatorConstraint({ name: 'customValidator', async: false })
export class AddParentRefConstraint implements ValidatorConstraintInterface {
defaultMessage(): string {
return '';
}
validate(
obj: object,
validationArguments: ValidationArguments,
): Promise<boolean> | boolean {
// add the parent ref on obj
const parentRef = new WeakRef(validationArguments.object);
Object.defineProperty(obj, 'parentRef', {
get: function () {
return parentRef;
},
});
Exclude()(obj, 'parentRef');
return true;
}
}
export function AddParentRef(validationOptions?: ValidationOptions) {
return function (target: object, propertyKey: string | symbol) {
return Validate(AddParentRefConstraint, validationOptions)(
target,
propertyKey,
);
};
}
A parentRef member is added in each object where the annotation is needed. Next, you can use it. I have using the @Exclude of class-transfomer on the property to ensure that the field if removed from serialisation, but if you you custom serialization, you should take care of it.
Next you can do this:
class Content1 {}
class Content2 {}
class A {
@IsValidContent()
content: Content1 | Content2;
}
class B {
@AddParentRef()
@Type(() => A)
@ValidateNested({ each: true })
a: A;
type: string;
}
export function IsValidContent(validationOptions?: ValidationOptions) {
return (object: Object, propertyName: string) => {
registerDecorator({
name: "isValidContent",
target: object.constructor,
propertyName,
constraints: [],
options: validationOptions,
validator: {
validate(value: any, args: ValidationArguments) {
const type = args.object.parentRef["type"];
switch (type) {
case "X":
return isValidType(value, Content1);
case "Y":
return isValidType(value, Content2);
default:
return false;
}
},
},
});
}
}