mui / material-ui

Material UI: Comprehensive React component library that implements Google's Material Design. Free forever.
https://mui.com/material-ui/
MIT License
93.31k stars 32.12k forks source link

[material-ui][Autocomplete] Make multiple selected values available to FormData #42988

Open TheRealCuran opened 1 month ago

TheRealCuran commented 1 month ago

Summary

When using <Autocomplete> for multiple values, the selected options should be made available like a native <select> through FormData. At the moment the input element passed to renderInput contains an empty string, when accessed through FormData (if you use a TextField), since it acts more as a visual and not a semantic container.

Side note: in the single value select case this works already through the TextField, which then contains the selected value.

Examples

We built a quick example of what we would like:

import { Autocomplete, Button, TextField } from '@mui/material'
import * as React from 'react'
import { Form, type ActionFunctionArgs } from 'react-router-dom'

const someOptions = [
  { label: 'Option1' },
  { label: 'Option2' },
  { label: 'Option3' },
]

export function AutoCompleteDemo() {
  return (
    <Form method="POST" action="/example">
      <Autocomplete
        options={someOptions}
        getOptionLabel={(option) => option.label}
        multiple
        renderInput={(params) => (
          <TextField
            {...params}
            required
            name="example"
            variant="outlined"
            label="Example"
          />
        )}
      />
      <Button type="submit">Submit</Button>
    </Form>
  )
}

export async function AutoCompleDemoAction(args: ActionFunctionArgs) {
  const formdata = await args.request.formData()
  // formdata.example should contain all selected values as a list
  console.log(formdata)
  return true
}

image

But as you can see, we get an empty string:

image

(And we were so far unable to fit a <Select> into the renderInput position, see also the Motivation segment.

Motivation

Using <Autocomplete> with <Form> from React Router requires additional code/custom components to make the selected option(s) available during form submission. It would be more elegant and semantically correct if you could just access the selected values through FormData – just like you already can with an <Autocomplete> for a single value.

And it doesn't seem to be really possible to feed a <Select> to <Autocomplete> (through renderOption for the <MenuItem>s and renderInput for the <Select>).

If it helps with the priority: we are a paying customer with the order ID 84512.

Search keywords: material ui, MUI, Autocomplete, FormData

ZeeshanTamboli commented 1 month ago

You can leverage hidden input fields i.e <input type="hidden" />:

import { Autocomplete, Button, TextField } from '@mui/material'
import * as React from 'react'
import { Form, type ActionFunctionArgs } from 'react-router-dom'

const someOptions = [
  { label: 'Option1' },
  { label: 'Option2' },
  { label: 'Option3' },
]

export function AutoCompleteDemo() {
  const [selectedOptions, setSelectedOptions] = React.useState([])

  return (
    <Form method="POST" action="/example">
      <Autocomplete
        options={someOptions}
        getOptionLabel={(option) => option.label}
        multiple
        onChange={(event, value) => setSelectedOptions(value)}
        renderInput={(params) => (
          <TextField
            {...params}
            required
            variant="outlined"
            label="Example"
          />
        )}
      />
      {selectedOptions.map((option, index) => (
        <input
          key={index}
          type="hidden"
          name="example"
          value={option.label}
        />
      ))}
      <Button type="submit">Submit</Button>
    </Form>
  )
}

export async function AutoCompleDemoAction(args: ActionFunctionArgs) {
  const formData = await args.request.formData()
  const selectedValues = formData.getAll('example')
  console.log(selectedValues)
  return true
}
TheRealCuran commented 1 month ago

Thank you for your reply. We know, that we can do it like that ourselves. But this was a feature request to make the access a native functionality – preferably semantically correct, but pure hidden input works as well. Especially since the documentation doesn't remark anywhere, that the single select and multi-select case behave different with regards to FormData.

In conclusion: we have a workaround like that operating here, but we want MUI's <Autocomplete> to handle this for us and offer us a "organic" interface to the data – no matter if we have a single or multi-value <Autocomplete>. ;-)

thomasmarr commented 1 week ago

@TheRealCuran I'm with you on this one. In the meantime I've shared the wrapper I'm using on #43544 in case it's of any use to you. Also interested to see what you are doing as a workaround.