jaredpalmer / formik

Build forms in React, without the tears 😭
https://formik.org
Apache License 2.0
34.01k stars 2.79k forks source link

Avoid validation by clicking on Link #2062

Open difagume opened 5 years ago

difagume commented 5 years ago

Hiii, someone could tell me how to avoid the submit by clicking on a Link to avoid validation, please.

When I click on the Link to go to another page the validation is executed and I have to click again to execute the navigation.

One solution is to remove the autoFocus from the Field, but I'd like to keep it.

it happens to me in Chrome, this is the code https://codesandbox.io/s/eloquent-moon-52m1v?fontsize=14&hidenavigation=1&theme=dark

captured

viniciusdacal commented 4 years ago

Hey @difagume. What triggers the validation in this case is blurring the input. You can either pass validateOnBlur={false} to Formik or remove autoFocus from your input.

googamanga commented 4 years ago

Formik needs an update to not block propagation on events. The proposed solutions are not satisfactory. Both reduce user experience

redux-form had similar issue: https://github.com/redux-form/redux-form/issues/860

Ended up switching from onClick to onMouseDown and onKeyDown to trigger event handler

gperez-10pines commented 3 years ago

We have a similar problem, but with a back button. Not sure why Formik validation prevents navigation.

onMouseDown and a keyboard event works. I'd suggest onKeyUp.

Be sure to include an href though. It's important for accessibility if you are using links.

Also, do check that the user is pressing the Enter key. Otherwise, the event will trigger even when the user presses the tab key.

One more thing: it would be proper to use onMouseUp instead. But that ends up in the same behavior that onClick.

<a
    href="#back-to-previous"
    onMouseDown={onClick}
    onKeyUp={(e) => {
      e.key === 'Enter' && onClick(e);
    }}
  >

That being said, this kinda forces you to do the same for every link, or at least to modify your Link component if you encapsulated the link in a custom component (best practice). So, it works but it should be another way.

gperez-10pines commented 3 years ago

I really couldn't figure out why the blur event prevents onClick to be executed. But a team fellow suggested a different approach, taking advantage of the relatedTarget attribute.

First, grab the field from the hook, or using function as a child if you prefer that. E.g: const [field] = useField(props);

Then, declare the onBlur event yourself, calling the Formik handler only if you are not clicking a link.

onBlur={(e) => {
  const wasLinkClicked = e.relatedTarget?.tagName === 'A'; <-- The ? symbol is typescript here
   if (!wasLinkClicked) {
      field.onBlur(e);
   }
}}

Note the ? symbol for typescript to prevent an error if you clicked outside a proper element.

Well, this approach concentrates the solution in Formik fields and not in the Link component.

I think none of these solutions is really clean, but you can choose one depending on your context anyway.

joelwilson005 commented 12 months ago

I'm having this issue as well. I can't believe that it hasn't been fixed as yet.