Vue Validation Composable: A Reusable Validation Tool
Building reusable components is a cornerstone of efficient Vue development. This challenge asks you to create a composable function in Vue 3 with TypeScript that handles form validation. This composable will take a validation schema as input and provide methods for validating a form, displaying errors, and tracking validation status.
Problem Description
You need to create a Vue composable named useValidation that simplifies form validation. The composable should accept a validation schema as an argument and provide the following functionalities:
validate(data: T): boolean: Validates the provided form data (data) against the validation schema. Returnstrueif the data is valid,falseotherwise.errors: Ref<Record<string, string | null>>: A reactive reference that holds the validation errors. The keys of the object correspond to the field names defined in the validation schema, and the values are the corresponding error messages (ornullif no error exists).isValid: Ref<boolean>: A reactive reference indicating the overall validation status of the form (true if valid, false otherwise).reset(): A function that clears all validation errors and resetsisValidtofalse.
The validation schema should be an object where keys are field names and values are validation rules. Each validation rule should be an array of functions. Each function in the array should take the field value as input and return an error message string if the validation fails, or null if the validation passes.
Key Requirements:
- The composable must be written in TypeScript.
- It must use Vue's reactivity system (
ref) to manage theerrorsandisValidstates. - The validation logic should be encapsulated within the composable.
- The composable should be generic, allowing it to work with different form data types.
Expected Behavior:
When validate is called, the composable should iterate through the validation schema, apply each validation rule to the corresponding field in the data, and update the errors and isValid states accordingly. If any validation rule fails, the corresponding error message should be stored in the errors object. isValid should be true only if all fields pass all validation rules.
Edge Cases to Consider:
- Empty validation schema.
- Fields in the data that are not defined in the validation schema.
- Validation rules that return non-string values (should be handled gracefully).
- Null or undefined values in the form data.
Examples
Example 1:
Input:
data: { email: 'test@example.com', age: 25 }
validationSchema: {
email: [
(value) => !value.includes('@') ? 'Invalid email format' : null,
],
age: [
(value) => value < 18 ? 'Must be at least 18 years old' : null,
],
}
Output:
errors: { email: null, age: null }
isValid: true
Explanation: Both email and age pass their respective validations.
Example 2:
Input:
data: { email: 'testexample.com', age: 15 }
validationSchema: {
email: [
(value) => !value.includes('@') ? 'Invalid email format' : null,
],
age: [
(value) => value < 18 ? 'Must be at least 18 years old' : null,
],
}
Output:
errors: { email: 'Invalid email format', age: 'Must be at least 18 years old' }
isValid: false
Explanation: Both email and age fail their validations, resulting in errors for both fields and isValid being false.
Example 3: (Edge Case - Empty Schema)
Input:
data: { name: 'John Doe' }
validationSchema: {}
Output:
errors: {}
isValid: true
Explanation: With an empty schema, no validations are performed, and the form is considered valid.
Constraints
- The composable must be generic, accepting a type parameter
Trepresenting the form data type. - Validation rules must return strings or
null. - The composable should be relatively performant; avoid unnecessary iterations or computations.
- The composable should be designed for reusability across different forms.
Notes
- Consider using
computedproperties to derive theisValidstate based on theerrorsobject. - Think about how to handle potential errors within the validation rules themselves (e.g., if a rule throws an exception). For simplicity, you can assume the validation rules are well-behaved.
- Focus on creating a clean, well-documented, and testable composable. While testing is not explicitly required for this challenge, consider how you would test your composable in a real-world scenario.
- The
reset()function should clear all errors and setisValidtofalse.