Passing Sitecore Fields to Form Validation Schema in Sitecore Headless Solution
In a Sitecore Headless Solution, you often need to integrate dynamic content from Sitecore into forms, such as passing Sitecore fields to a form validation schema. While accessing Sitecore item fields within a component is straightforward when the schema is defined inside the component, reusing that schema across different components can present challenges. In this blog post, we will walk through two scenarios: one where the validation schema is defined inside the component function and another where it is defined outside the component function. We will also explore how to overcome the challenges of passing Sitecore fields to a schema defined outside the component.
Scenario 1: Schema Defined Inside the Component Function
In the first scenario, we define a simple form within the RegisterUser component, and the validation schema is declared inside the same component function. The form contains two fields: firstName and lastName, and each field has its own validation message fetched from Sitecore fields.
Here’s the code for this scenario:
tsx
Copy code
const RegisterUser = (props: RegistrationProps): JSX.Element => {
const schema = z.object({
firstName: z.string().nonEmpty({ message: props.fields.FirstNameValidation.value }),
lastName: z.string().nonEmpty({ message: props.fields.LastNameValidation.value }),
});
const form = useForm({
initialValues: {
firstName: ”,
lastName: ”,
},
validate: zodResolver(schema),
validateInputOnBlur: true,
});
return <></>;
}
In this example, the props.fields.FirstNameValidation.value and props.fields.LastNameValidation.value are passed to the schema for validation messages. Since the schema is defined inside the component, it’s easy to use dynamic data from Sitecore to populate the validation messages.
Scenario 2: Schema Defined Outside the Component Function
Now, let’s say we want to reuse the schema across different components. To achieve this, we move the validation schema outside the RegisterUser component and export it for reuse.
Here’s how the updated code looks:
tsx
Copy code
const schema = z.object({
firstName: z.string().nonEmpty({ message: ‘Please enter first name’ }),
lastName: z.string().nonEmpty({ message: ‘Please enter last name’ }),
});
export type RegistrationForm = z.infer<typeof schema>;
const RegisterUser = (props: RegistrationProps): JSX.Element => {
const form = useForm({
initialValues: {
firstName: ”,
lastName: ”,
},
validate: zodResolver(schema),
validateInputOnBlur: true,
});
return <></>;
}
In this case, the validation messages are hardcoded, and we no longer have the flexibility to pass error messages from Sitecore, since the schema is defined outside the component. So, how do we pass dynamic Sitecore fields to this schema when it’s defined outside the component?
Solution: Convert the Schema to a Function
To solve this, we need to convert the schema into a function that accepts dynamic input, such as Sitecore field values. This way, we can still reuse the schema, while passing Sitecore-specific error messages to it.
Here’s the solution:
- Create a New Interface: Define an interface that contains only the necessary error messages from Sitecore. This improves readability and maintains separation of concerns.
- Modify the Schema: Convert the schema into a function that accepts the error messages as input.
- Pass the Sitecore Fields: Pass the Sitecore fields to the schema function from within the component.
tsx
Copy code
interface RegistrationFormErrors {
FirstNameValidation: Field<string>;
LastNameValidation: Field<string>;
}
const schema = (props: RegistrationFormErrors) => {
return z.object({
firstName: z.string().nonEmpty({ message: props.FirstNameValidation.value }),
lastName: z.string().nonEmpty({ message: props.LastNameValidation.value }),
});
}
export type RegistrationForm = z.infer<ReturnType<typeof schema>>;
const RegisterUser = (props: RegistrationProps): JSX.Element => {
const form = useForm({
initialValues: {
firstName: ”,
lastName: ”,
},
validate: zodResolver(schema(props.fields)),
validateInputOnBlur: true,
});
return <></>;
}
Explanation of the Solution
- Interface for Error Messages: We define an interface RegistrationFormErrors that contains only the necessary error messages for validation.
- Schema as a Function: The schema is now a function that takes props (containing Sitecore fields) and returns the validation schema. This makes it possible to pass dynamic error messages from Sitecore.
- Usage in Component: In the RegisterUser component, we call the schema function and pass props.fields as an argument. This ensures that the Sitecore-specific validation messages are correctly integrated into the schema.
- Reusability: With this solution, we can reuse the schema function across different components while passing dynamic Sitecore field values to customize the error messages.
Conclusion
Passing Sitecore fields to a form validation schema can be tricky when the schema is defined outside the component function. However, by converting the schema into a function and passing dynamic Sitecore data as input, we can overcome this challenge. This approach ensures that you can reuse your validation logic while maintaining the flexibility of dynamic content from Sitecore, making your forms both modular and customizable in a headless Sitecore solution.