final-form / react-final-form

🏁 High performance subscription-based form state management for React
https://final-form.org/react
MIT License
7.38k stars 479 forks source link

Submit from FormSpy #135

Open danizord opened 6 years ago

danizord commented 6 years ago

Are you submitting a bug report or a feature request?

Feature request

What is the current behavior?

FormSpy receives FormState and SubsetFormApi, but as far I know it does not receive any method to trigger a form submit.

What is the expected behavior?

The SubsetFormApi could include the submit() method.

Other information

The "Auto-Save with Debounce" example could benefit from it, submitting the form instead of expecting a save prop to be passed.

klis87 commented 6 years ago

I think this would be really useful. My use case is that I have 2 possible handlers for onSubmit, but I can only have 1 submit button (or more but with some hacks ;)). With handleSubmit available in FormSpy, I could do:

<button
  type="button"
  onClick={(e) => {
    setSomeStateToMark2ndHandlerAsActiveInOnSubmit();
    handleSubmit(e);
  }}
/>

Without it, I need to get form ref and submit via DOM method or to pass handleSubmit as prop deep in my component tree.

But maybe having multiple different handlers for submit could be achieved in a different way?

redbmk commented 6 years ago

What's the downside to letting FormSpy have direct access to form (the formApi)? If we could get access to that, we could submit directly from there. We could also access the list of registered fields if we needed to (I vaguely recall an example of doing this by accessing the DOM instead of via props, but maybe that was part of final-form). As far as I can tell, the only way to access the form API is from the onSubmit callback.

mmakarin commented 3 years ago

You can gain access to form instance using useForm hook inside your custom component. Something like that.

const AutoSave = () => {
  const form = useForm();

  const triggerSubmit = useDebouncedCallback(
    ({valid, dirty}) => valid && dirty && form.submit(),
    500
  );

  return (
    <FormSpy
      onChange={triggerSubmit}
      subscription={{values: true, valid: true, dirty: true}}
    />
  );
};

<Form>
    <form>
      <AutoSave />
    </form>
  </Form>```