Skip to content

Instantly share code, notes, and snippets.

@sohseyedi-web
Last active January 15, 2025 17:46
Show Gist options
  • Select an option

  • Save sohseyedi-web/18b2add362ec95173c2a3eb59816edf0 to your computer and use it in GitHub Desktop.

Select an option

Save sohseyedi-web/18b2add362ec95173c2a3eb59816edf0 to your computer and use it in GitHub Desktop.
//types
import type { Ref } from "vue";
import type { z, ZodTypeAny } from "zod";
export type ZodFormType<T extends ZodTypeAny> = z.infer<T>;
export interface ValidateFormType<T extends ZodTypeAny> {
values: ZodFormType<T>;
schema: T;
errors: Ref<Record<string, string>>;
field?: keyof ZodFormType<T>;
}
//utils
import type { ValidateFormType, ZodFormType } from '@/types'
import type { ZodTypeAny } from 'zod'
export function validateForm<T extends ZodTypeAny>({ values, schema, errors }: ValidateFormType<T>): boolean {
const res = schema.safeParse(values)
if (res.success) {
errors.value = {}
return true
}
else {
const formErrors: Record<string, string> = {}
for (const [key, val] of Object.entries(res.error.formErrors.fieldErrors)) {
formErrors[key] = Array.isArray(val) ? val[0] : val || ''
}
errors.value = formErrors
return false
}
}
export function validateField<T extends ZodTypeAny>({ values, schema, errors, field }: ValidateFormType<T>) {
try {
const res = schema.safeParse(values) as ZodFormType<T>
const error = res.success ? '' : res.error.formErrors.fieldErrors[field]
errors.value[field as string] = Array.isArray(error) ? error[0] : error || ''
}
catch {
}
}
//useValid
import type { ZodTypeAny } from 'zod'
import { validateField, validateForm } from '@/utils'
import { ref, watch } from 'vue'
import { z } from 'zod'
function useValid<T extends ZodTypeAny>(initialValues: unknown,schema: T) {
type ZodForm = z.infer<T>
const values = ref<ZodForm>(initialValues)
const errors = ref<Record<string, string>>({})
const isValidForm = ref<boolean>(false)
const runValidation = () => {
isValidForm.value = validateForm({ values: values.value, schema, errors })
}
watch(
values,
(newValues: ZodForm) => {
for (const fieldName of Object.keys(newValues)) {
validateField({ values: values.value, schema, errors, field: fieldName })
}
runValidation()
},
{ deep: true },
)
runValidation()
return {
values,
errors,
isValidForm,
validateField,
}
}
//schema
export const exampleSchema = z.object({
text: z
.string()
.min(1, 'Error')
})
// code
const { errors, validateForm, values } = useValid({ text: '' }, exampleSchema)
function onSubmit() {
console.log(values.value)
}
<input
v-model="values.text"
type="text"
placeholder="..."
name="text"
/>
<span>{{errors.text}}</span>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment