radix-ui / primitives

Radix Primitives is an open-source UI component library for building high-quality, accessible design systems and web apps. Maintained by @workos.
https://radix-ui.com/primitives
MIT License
15.08k stars 740 forks source link

[Slider] Allow individual `name` attribute on each thumb. #2454

Closed nd55 closed 4 months ago

nd55 commented 9 months ago

Feature request

Overview

Hello there :)

I implemented a Radix Slider inside a search/filter form with two Thumbs in an app I am currently building. Currently, only <Slider.Root> allows one name as attribute and both auto generated hidden inputs get the same name appended with []:

<Slider.Root name="testname">…

{/* Current result */}
<input value="46" style="display: none;" name="testname[]">
<input value="101" style="display: none;" name="testname[]">

For my use case have a range with a min- and max-value for a given setting. When submitting the form, I need both of these values to have a different name, filters[layout][space][min] and filters[layout][space][max].

I'd like to propose the option to give each Thumb an individual name, which would look like this:

<Slider.Root  … >
  <Slider.Track>
    <Slider.Range />
  </Slider.Track>

  <Slider.Thumb name="filters[layout][space][min]" />
  <Slider.Thumb name="filters[layout][space][max]" />
</Slider.Root>

{/* Result */}
<input value="46" style="display: none;" name="filters[layout][space][min]">
<input value="101" style="display: none;" name="filters[layout][space][max]">

If no individual name is provided, it would fallback to the Root's name, or otherwise no name.

Thank you for reading – I'd appreciate any feedback or considerations regarding this feature proposal. ☺️

vincerubinetti commented 8 months ago

Just ran into this too trying to use a range with FormData. Fairly big hole here. The name="fieldname[]" makes me think this is an oversight and not intentional.

I like your idea of being able to assign a unique name to each thumb. You're not talking about doing some kind of templating with those [min][layout] right? Probably easier and clearer to just let us set it to whatever, e.g. <Thumb name=`filters-${min}` />

A workaround for now could be to find those generated hidden inputs in a useEffect and correct their names manually:

  useEffect(() => {
    const root = ref.current;
    if (!root) return;
    const inputs = [...(root.parentElement?.querySelectorAll("input") || [])];
    if (inputs.length > 1)
      for (const [index, input] of Object.entries(inputs))
        input.name = props.name + "-" + index;
  });

🤮


Edit: @nd55's solution below is probably better. Only thing is it still leaves the Radix hidden input with name="filters[]" and will "pollute" your FormData. Probably not an issue for most people though.

nd55 commented 8 months ago

@vincerubinetti Thanks for your feedback! I solved this similar to your solution, by creating a useState for each thumb and mapping the names and values on extra hidden inputs I added in my component.

const [minValue, setMinValue] = useState(minDefault)
const [maxValue, setMaxValue] = useState(maxDefault)

return (
  <Slider.Root
    onValueChange={(values) => {
      setMinValue(values[0])
      setMaxValue(values[1])
    }}
  >
    ...
    <input type="hidden" name={minValueName} value={minValue} />
    <input type="hidden" name={maxValueName} value={maxValue} />
  </Slider.Root>
)

The bracket syntax with [min][layout] is just the way our backend needs the name to be submitted as, I did not mean it as a template :)

benevbright commented 5 months ago

@nd55 pretty good solution. thanks.

benoitgrelard commented 4 months ago

That seems like a sensible request.

I like your idea of being able to assign a unique name to each thumb. You're not talking about doing some kind of templating with those [min][layout] right?

The point is form serialization, there are environments and libs that support automatically serializing things into object based on these types of names.

I've opened a PR here adding this new ability: https://github.com/radix-ui/primitives/pull/2766