useForm.ts 1.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253
  1. import { reactive } from 'vue'
  2. import { object, setLocale, AnySchema, ValidationError } from 'yup'
  3. import { debounce } from 'lodash-es'
  4. import Toast from '@/components/toast'
  5. type FormSchemaShap<T> = {
  6. [K in keyof T]?: AnySchema
  7. }
  8. interface FormOptions<T> {
  9. initialValues?: Partial<T>
  10. valuesRef?: T
  11. schema: FormSchemaShap<T>
  12. }
  13. export default function useForm<Shap extends object>(
  14. options: FormOptions<Shap>
  15. ) {
  16. const values: Partial<Shap> =
  17. options.valuesRef || reactive<Partial<Shap>>(options.initialValues || {})
  18. const handleSubmit = debounce(
  19. function (
  20. onSubmit: (values: Partial<Shap>) => any,
  21. onInvalidSubmit?: (error: ValidationError) => any
  22. ) {
  23. object(options.schema as any)
  24. .validate(values)
  25. .then(() => onSubmit(values))
  26. .catch((err: ValidationError) => {
  27. Toast(err.message)
  28. onInvalidSubmit?.(err)
  29. })
  30. },
  31. 500,
  32. { leading: true, trailing: false }
  33. )
  34. const reset = () => {
  35. Object.keys(values).forEach(key => delete (values as any)[key])
  36. }
  37. return { values, handleSubmit, reset }
  38. }
  39. setLocale({
  40. mixed: {
  41. required: '${path} is required',
  42. },
  43. string: {
  44. email: 'invalid ${path}',
  45. },
  46. })