adobe / react-spectrum

A collection of libraries and tools that help you build adaptive, accessible, and robust user experiences.
https://react-spectrum.adobe.com
Apache License 2.0
12.85k stars 1.11k forks source link

Add "form" attribute to buttons of type="submit" #1456

Open undavide opened 3 years ago

undavide commented 3 years ago

πŸ™‹ Feature Request

It would be nice to have a "form" attribute for React Spectrum Buttons, when they are of type="submit".

πŸ”¦ Context

See the following example coming from the React Spectrum examples page:

<DialogTrigger>
  <ActionButton>Register</ActionButton>
  {(close) => (
    <Dialog>
      <Heading>
        <Flex alignItems="center" gap="size-100">
          <Book size="S" />
          <Text>Register for newsletter</Text>
        </Flex>
      </Heading>
      <Header>
        <Link>
          <a href="//example.com" target="_blank">
            What is this?
          </a>
        </Link>
      </Header>
      <Divider />
      <Content>
        <Form>
          <TextField label="First Name" placeholder="John" autoFocus />
          <TextField label="Last Name" placeholder="Smith" />
          <TextField label="Street Address" placeholder="123 Any Street" />
          <TextField label="City" placeholder="San Francisco" />
        </Form>
      </Content>
      <Footer>
        <Checkbox>
          I want to receive updates for exclusive offers in my area.
        </Checkbox>
      </Footer>
      <ButtonGroup>
        <Button variant="secondary" onPress={close}>
          Cancel
        </Button>
        <Button variant="cta" onPress={close}>
          Register
        </Button>
      </ButtonGroup>
    </Dialog>
  )}
</DialogTrigger>

image

The dialog is nicely designed, and the content is kept separate in the <Heading>, <Content>, and <Footer>.

Problem is that the ButtonGroup, which very likely contains a submit button in such Dialogs, belongs to the Footer, i.e. it's not contained within the <Form> component – hence it can't act as a Button of type="submit".

In HTML it's possible to add a form attribute to a submit Button, so that it can work regardless to its positioning. E.g.

<form id="aForm">
  <!-- stuff -->
</form>
<button type="submit" form="aForm">Submit</button>

A similar possibility for <Form> and React Buttons would be nice to have.

Thanks!

LFDanLu commented 3 years ago

@undavide Allowing the form attribute on a button seems pretty reasonable, lemme double check with the team just in case.

devongovett commented 3 years ago

I'm guessing this is related to wanting the enter key to trigger the submit button's action? I'm having a hard time imagining wanting to submit a form in a dialog via the browser which would trigger a full page reload.

If so, it seems related to #855

undavide commented 3 years ago

Uhm, actually no, my feat request was specifically only about being able to use a submit button when the button itself can't be inside the <form>

razvanip commented 3 years ago

i think there are some other libraries out there regarding forms that usually really on a submit button being present in the form to handle submit

dmbaughman commented 2 years ago

Since the <Button> component in Spectrum is an implementation of the native <button> element, shouldn't it support all the native attributes?
https://developer.mozilla.org/en-US/docs/Web/HTML/Element/button#attr-form


I have a similar use case where I was trying to put a form inside the content area of a dialog, and then include a submit button in the footer of the dialog, because wrapping the input and submit buttons in the same <Form> component was breaking the dialog layout.

Notional example of dialog with form fields in content section and submit button in footer
tchak commented 1 year ago

I think Button should also have name, value, formmethod and formaction attributes. They are all very useful when working with forms. And in frameworks like remix-run forms are used to trigger any actions (they do not trigger full reloads like it was mentioned earlier). In some cases this approach makes it simpler to implement a basic experience even if JavaScript fails for some reason.

Spooky-0 commented 1 year ago

I'm struggling with the same Issue. My very ugly workaround right now is to add

  useEffect(() => {
    ref.current?.UNSAFE_getDOMNode().setAttribute("form", "new-field-form");
  }, [ref]);
donaldr commented 5 months ago

I've also run into this issue. I have a situation where I'm trying to deal with a nested form. The natural conclusion is instead to have self-closing forms with ids that the inputs then refer to. This doesn't seem possible to do with react-spectrum.

CHE1RON commented 4 months ago

As outlined in https://github.com/adobe/react-spectrum/discussions/6481, I think this is a very important issue, as this would be universally applicable & areas of application are manifold. The Dialog modal component is perfect for submitting any kind of form data, and as @undavide pointed out, the great default design should not be compromised in order to achieve something like that - up to now, I put ButtonGroup inside Content and added the margin etc myself, having to integrate Footer manually, and well .. sigh

Beware though that we'd need a solution which takes into account not only Content, but also eg Footer (see the checkbox in OP's example) πŸ™