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

<Select> component <form> compatability #799

Open
cliffordfajardo opened this issue Jul 19, 2022 · 4 comments
Open

<Select> component <form> compatability #799

cliffordfajardo opened this issue Jul 19, 2022 · 4 comments

Comments

@cliffordfajardo
Copy link

cliffordfajardo commented Jul 19, 2022

Description

Currently <Select> component is not fully <form> compatible, which means when you submit a <Form> or <form> the data from the <Select> is not included in the form submission.



How to Reproduce Bug

Submit a form which contain's <Select> (see video below or see codesandbox here)

  • observe that form submission does not update the URL
  • observe that no data is being sent to the backend
    000-ant_select--vs-select.mp4



Motivation For Changes

1. HTML <form> compatibility

  • Being <form> compliant means that people have the additional option of using Ant's <Select> in a similar way to using a standard<select> without losing the great UX/UI that <Select> offers (for example using <Select showSearch> is awesome!)

2. Many of Ant design's existing form-related components are already <form> compliant

  1. Removes the need for a user of Ant Design to manually add hidden input fields . This is the same issue Tailwind Headless UI had but solved in this pull request



Proposition of Changes

The proposed changes below are backwards compatible:

  1. allow user to pass name prop to <Select> to achieve feature compliance with regular<select> which does allow name prop (Ex: <select name="vehicle"> ).
    CleanShot 2022-07-19 at 08 46 57@2x

  2. When a user passes name prop to <Select> generate a hidden input (<input type="hidden" name={selectProps.name}>) and when the user selects the value from the list, add value attribute to the hidden input and set it to the selected value (<input type="hidden" name={selectProps.name} value={selected_value}>. Inspiration for this implementation comes from Tailwind's Headless UI react library (Github Pull Request)

For single item selection (fake code for demonstrative purpose)

<Select showSearch style={{ width: 300 }} name="job_title">
    <Select.Option value="engineer">engineer</Select.Option>
    <Select.Option value="teacher">teacher</Select.Option>
      // This hidden input would get generated from <Select> when a `name` prop is provided
     // <input type="hidden" name={select.props.name} value={the_selected_value}>
</Select>

For multi selection (fake code for demonstrative purpose) mode=tags | multiple

<Select showSearch style={{ width: 300 }} name="job_title">
    <Select.Option value="engineer">engineer</Select.Option>
    <Select.Option value="teacher">teacher</Select.Option>
      // Any time a new item is selected a new  hidden input is generated from <Select> when a `name` prop is provided
     // <input type="hidden" name={select.props.name} value={the_selected_value}>
     // <input type="hidden" name={select.props.name} value={the_selected_value}>
</Select>


Summary

To solve this, <Select> needs name prop support & it needs to generate a hidden <input> element for the selected value


References

Documentation for <form> comptability

Related Issues

@chalkedgoose
Copy link

chalkedgoose commented Jul 19, 2022

native form compatibility would be a big win!

@manzaloros
Copy link

The more compatibility the better. I didn't realize there wasn't native <form> compatibility until this issue was raised.

@guepjo
Copy link

guepjo commented Jul 19, 2022

Encountered this issue a couple weeks ago and couldn't find any work around. Adding this feature would be greatly appreciated!

@kevinreber
Copy link

kevinreber commented Jul 19, 2022

Thanks for documenting all this @cliffordfajardo
The proposed changes would also help out a lot with e2e testing.

The way the current Select component is generated in the DOM, makes it tricker to select the Select component and verify values in e2e testing.

Example

React Code

// AntDesign Select component
<Form.Item label="AntDesign Selector" name="Ant-Selector-FormItem">
  <Select data-testid="Ant-Selector">
    <Select.Option value="YES">YES</Select.Option>;
    <Select.Option value="NO">NO</Select.Option>;
  </Select>
</Form.Item>

DOM

// AntDesign Select component Generated in DOM
<div class="ant-select ant-select-single ant-select-show-arrow" data-testid="Ant-Selector">
  <div class="ant-select-selector">
    <span class="ant-select-selection-search">
      <input type="search" id="Ant-Selector-FormItem" autocomplete="off" class="ant-select-selection-search-input" role="combobox" aria-haspopup="listbox" aria-owns="Ant-Selector_list" aria-autocomplete="list" aria-controls="Ant-Selector_list" aria-activedescendant="Ant-Selector_list_0" readonly="" unselectable="on" value="" style="opacity: 0;">
    </span>
    <span class="ant-select-selection-item" title="YES">YES</span>
  </div>
  <span class="ant-select-arrow" unselectable="on" aria-hidden="true" style="user-select: none;">
    <span role="img" aria-label="down" class="anticon anticon-down ant-select-suffix">
      <svg viewBox="64 64 896 896" focusable="false" data-icon="down" width="1em" height="1em" fill="currentColor" aria-hidden="true">
        <path d="M884 256h-75c-5.1 0-9.9 2.5-12.9 6.6L512 654.2 227.9 262.6c-3-4.1-7.8-6.6-12.9-6.6h-75c-6.5 0-10.3 7.4-6.5 12.7l352.6 486.1c12.8 17.6 39 17.6 51.7 0l352.6-486.1c3.9-5.3.1-12.7-6.4-12.7z"></path>
      </svg>
    </span>
  </span>
</div>

e2e Testing using Playwright

// e2e Test for Selector component
  test('Get AntDesign Selector value', async ({ page }) => {

    // When clicking on a Selector component in AntDesign, the value is not stored in the input element
    // AntDesign creates a new span element, that stores/renders the selected value
    // We need to check this span to ensure the value is updated
    const AntSelectorValue = page.locator(
      '[data-testid="Ant-Selector"] .ant-select-selector>span.ant-select-selection-item',
    );

    // Ideally we would want to use `.inputValue()` instead of `.innerText()`,
    // but since our `Select` value is stored in a `span` we can NOT use `.inputValue()`
    expect(await AntSelectorValue.innerText()).toBe('YES');
    expect(await AntSelectorValue.innerText()).not.toBe('NO');
  });

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