Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add TypeScript Return Types for useForm #16

Closed
pixelmund opened this issue Jun 8, 2023 · 4 comments
Closed

Add TypeScript Return Types for useForm #16

pixelmund opened this issue Jun 8, 2023 · 4 comments

Comments

@pixelmund
Copy link

pixelmund commented Jun 8, 2023

Currently the Inertia useForm for React and Vue has a return type of any, it would be awesome to have it typed.

EDIT: Actually when testing on my fork, we can probably get rid of the implicit any return and let typescript infer the type correctly, but it's giving me an weird error on the vue-inertia package. So probably better to type it!

@timacdonald
Copy link
Member

We will likely improve this soon. Going to close, however, as it isn't a functional bug.

@madsh93
Copy link

madsh93 commented Sep 28, 2023

@pixelmund

I've made a quick vue composable which covers the basics. Not at all a complete solution.

import { reactive, ref, watch } from 'vue';
import type { RequestMethod, SimpleValidationErrors, ValidationConfig, ValidationErrors } from 'laravel-precognition';
import { useForm } from 'laravel-precognition-vue-inertia';
import type { VisitOptions } from '@inertiajs/core';

export function useFormPrecognition<Data extends Record<string, unknown>>(
  method: RequestMethod | (() => RequestMethod),
  url: string | (() => string),
  inputs: Data,
  config: ValidationConfig = {}
): Data & {
    submit: (options?: Partial<VisitOptions>) => void;
    invalid: (label: keyof Data) => boolean;
    validate: (label: keyof Data) => void;
    processing: boolean;
    validating: boolean;
    hasErrors: boolean;
    forgetError: (label: keyof Data) => void;
    reset: () => void;
    setData: (label: keyof Data, value: unknown) => void;
    errors: { [label in keyof Data]: ValidationErrors | SimpleValidationErrors };
    isDirty: boolean;
    isFieldDirty: (label: keyof Data) => boolean;
    initialFieldValue: (label: keyof Data) => unknown;
    data: () => Data;
  } {
  const initialState = reactive({ ...inputs });
  const form = useForm(method, url, inputs, config);
  const isDirtyRef = ref(false);

  watch(
    () => form.data(),
    (newVal, _oldVal) => {
      isDirtyRef.value = JSON.stringify(initialState) !== JSON.stringify(newVal);
    },
    { deep: true }
  );

  function isFieldDirty(label: keyof Data): boolean {
    const currentData = form.data() as Record<keyof Data, unknown>;
    const initialData = initialState as Record<keyof Data, unknown>;
    return JSON.stringify(initialData[label]) !== JSON.stringify(currentData[label]);
  }

  function initialFieldValue(label: keyof Data): unknown {
    const initialData = initialState as Record<keyof Data, unknown>;
    return initialData[label];
  }

  // Proxying form object to add isDirty property
  const state: any = new Proxy(form, {
    get(target, prop: string) {
      if (prop === 'isDirty') {
        return isDirtyRef.value;
      }
      if (prop === 'isFieldDirty') {
        return isFieldDirty;
      }
      if (prop === 'initialFieldValue') {
        return initialFieldValue;
      }

      return target[prop];
    },
    set(target, prop: string, value) {
      if (prop === 'isDirty') {
        isDirtyRef.value = value;
        return true;
      }
      target[prop] = value;
      return true;
    }
  });

  return state;
}

@lk77
Copy link

lk77 commented Aug 9, 2024

is there a way to import a type from laravel-precognition-vue-inertia ?

i'm doing that :

const form: Ref<{submit: Function, clearErrors: Function, reset: Function}|null> = ref(null);

with the functions i plan to use,
but that's a little ugly.

It's an edit form, and i need to wait for the user to actually edit something before calling useForm,
it works great, but i need to tell ts what that ref gonna hold

edit:

This seems to work :

const form: Ref<ReturnType<typeof useForm>|null> = ref(null);

@joelstein
Copy link

See #110.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants