Yup - create and modify a validation schema at runtime

Viewed 2059

I need to create a user and then update it. So I need two different schema.

This is the first one, for the user creation:

const addressSchema = object().shape({
    street: string().required(),
    city: string().required(),
});

const signUpSchema = object().shape({
    req: object().shape({
        username: string().trim().required(),
        password: string().trim().required(),
        role: string().trim().required(),
        address: addressSchema
            .default(null)
            .nullable()
            .when(role, isAdminRole(object().required()))
    })
})

Now, I would like to reuse the schema above for the customer's update operation. But, it can't be equals because in the update operation, for example, I don't want to change the password. Second, it can't have .required() restriction. Because, in the update operation, maybe, I want to modify only the username and not also the role. This is how the update schema should look like:

const addressUpdateSchema = object().shape({
    street: string().min(1), // .min(1) because it's not a required field but it can't be an empty string neither
    city: string().min(1),
});

const updateSchema = object().shape({
    req: object().shape({
        username: string().trim().min(1), 
        role: string().trim().min(1),
        address: addressUpdateSchema
            .default(null)
            .nullable()
            .when(role, isAdminRole(object()))
    })
})

In order to achieve these schemas, this is what I did:

1 - Creating an array of objects containing the validation fields:

const signUpValidationSchemaArray = [
{ name: 'username', validation: string().trim().required() },
{ name: 'password', validation: string().trim().required() }
{ name: 'role', validation: string().trim().required() }
{ name: 'address', validation: addressSchema.default(null).nullable().when(role, isAdminRole(object().required()))}

2 - Writing a function that returns a yup schema starting from the array above:

const buildYupSchema = (fields: any[]) => {
    const newSchema = {};
    fields.forEach(field => newSchema[field.name] = field.validation);
    return object().shape(newSchema);
}

buildYupSchema(signUpValidationSchemaArray);

Doing this we create the const signUpSchema = object().shape({ ... schema declared above. Now, I want to create the const updateSchema = object().shape({ ... schema using the already written code as much as possible.

3 - Here's the problem, I'm trying to modify the validation fields of signUpValidationSchemaArray

const updateValidationSchemaArray = [...signUpValidationSchemaArray].filter(field => field.name !== 'password' )
.map(field => {
        name: field.name,
        validation: field.validation.notRequired()
    }
});

buildYupSchema(updateValidationSchemaArray);

.filter(field => field.name !== 'password' ) -> I want exclude password since I don't want to modify it in the update operation

validation: field.validation.notRequired() -> I want to remove required() restriction. I tried doing this, adding notRequired(); but it's not working. Maybe it would be better to remove .required() directly, somehow. But I don't know how to do this.

  • Any suggestions?
  • Is this a good approach to achieve what I want?
1 Answers

I am using reactive if conditions for two , this works

let schema; // IMPORTANT!!!!!!!

$: if (editId && !blockUser && !resetPass) {
//validation for edit info
schema = yup.object().shape({
  email: yup.string().required().email().label("Email"),
  mobile: yup
    .number()
    .typeError("Mobile is a requried field")
    .label("Mobile No"),
});
} else {
//validation for add
schema = yup.object().shape({
  full_name: yup.string().required().max(30).label("Full Name"),
  email: yup.string().required().email().label("Email"),
  password: yup.string().required().min(8).label("Password"),
  mobile: yup
    .number()
    .typeError("Mobile is a requried field")
    .label("Mobile No")
});
}
Related