Skip to content

Instantly share code, notes, and snippets.

@NikitaIT
Created July 4, 2021 20:28
Show Gist options
  • Save NikitaIT/3dd2ff4073977f085419f1709b075a60 to your computer and use it in GitHub Desktop.
Save NikitaIT/3dd2ff4073977f085419f1709b075a60 to your computer and use it in GitHub Desktop.
Vee validate handleSubmit with invalid callback
import { PublicFormContext, SubmissionHandler } from "vee-validate";
export function createSubmitHandler<
TValues extends Record<string, any> = Record<string, any>,
TContext extends Omit<PublicFormContext<TValues>, "handleSubmit"> = Omit<
PublicFormContext<TValues>,
"handleSubmit"
>
>(
onValid: SubmissionHandler<TValues>,
onInvalid: (
formValues: {
handleSubmit: (
event: Event,
cb: SubmissionHandler<TValues>
) => Promise<void>;
} & TContext
) => void
): (
event: Event,
formValues: {
handleSubmit: (
event: Event,
cb: SubmissionHandler<TValues>
) => Promise<void>;
} & TContext
) => Promise<void> {
return (event, formValues) => {
const { promise, resolve, reject } = deffer();
promise.catch(() => onInvalid(formValues));
const handle: SubmissionHandler<TValues> = (...args) => (
resolve(), onValid(...args)
);
return formValues.handleSubmit(event, handle).then(reject);
};
}
type Executor<T, TErr> = {
resolve: (value?: T) => void;
reject: (reason?: TErr) => void;
};
function deffer<T, TError>(): { promise: Promise<T> } & Executor<T, TError> {
let control: any;
const promise = new Promise<T>(
(resolve, reject) => (control = { resolve, reject })
);
return {
resolve: control.resolve,
reject: control.reject,
promise,
};
}
@NikitaIT
Copy link
Author

NikitaIT commented Jul 4, 2021

How to use:

<Form as="" v-slot="formCtx">
    <form 
      novalidate
      validateOnMount // for errors in formCtx on first submit
      ref="formRef"
      @submit="handleSubmit($event, formCtx)"></form>
</Form>

Example with Focus on first invalid contorl in dom order:

setup() {
   const submit = /* same as in vee handleSubmit */;
   const formRef = ref();
   return {
      formRef,
      handleSubmit: createSubmitHandler<any>(submit, (formCtx) => {
        console.log("form not valid", formCtx);
        const form = formRef.value!;
        const firstInvalidControlInDomOrder = getFirstInvalidControlInDomOrder(form, errors);
        firstInvalidControlInDomOrder?.focus();
      }),
  };
}
function getFirstInvalidControlInDomOrder(
  form: HTMLFormElement,
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  errors: any
): HTMLInputElement | undefined {
  return Array.from(form.elements as unknown as HTMLInputElement[]).find(
    (x) => x.name in errors
  );
}

@git-e-001
Copy link

Please use this away with composition api
logaretm/vee-validate#427 (comment)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment