svelte-multiselect icon indicating copy to clipboard operation
svelte-multiselect copied to clipboard

Option grouping

Open lysdexic-audio opened this issue 1 year ago • 8 comments

This is a perfect little component. In some cases where there are many fields it would be nice if a single Multiselect could contain several options, perhaps like this:

<script>
  import MultiSelect from 'svelte-multiselect'

  const genreTags = [`Rock`, `Electronic`, `Opera`]
  const keyTags = [`C`, `D`, `E`, `F`, `G`, `A`, `B`]
  const scaleTags = [`Major`, `Minor`]

  let selectedTags = []
</script>

<MultiSelect
  bind:selectedTags
  options={[genreTags, keyTags, scaleTags]}
  maxSelect={[null, 1, 1]}
  required={[true, true, false]}
  placeholder="Select Tags"
/>

I need this in my app - are you open to an PR (if this isn't already supported)?

lysdexic-audio avatar Oct 17 '22 21:10 lysdexic-audio

Why do they need to be in 1 multi-select? And what would the UI for that look like? How would you have 3 dropdowns in one component? Maybe you can elaborate on your use case.

janosh avatar Oct 17 '22 21:10 janosh

Hey thanks for the quick reply - I'm referring to a binding to the HTML optgroup element

https://developer.mozilla.org/en-US/docs/Web/HTML/Element/optgroup

lysdexic-audio avatar Oct 17 '22 22:10 lysdexic-audio

Ah, you're talking about grouping of options. Yes, I'd be happy to take a PR for that.

I should say upfront though, this sounds like a fair amount of work if you want to do it right. Your example suggests that you don't just want option grouping in the UI but for the groups to have separate maxSelect and required attributes. That raises some questions:

  1. What should happen when users create new options (when allowUserOptions=true)? Which group should the new option be added to?
  2. Does each group have separate defaultDisabledTitle?

janosh avatar Oct 17 '22 22:10 janosh

Yes, exactly - not quite just the grouping of options, since the intention is to group other attributes from Multiselect like maxSelect....

  1. allowUserOptions could be either disabled for this feature or treated in the same way ie: boolean | boolean[]. When more than one option allows user options the optgroup label could be required for input - for example, input text like: genre=Electronic for something like the following:
<script>
  import MultiSelect from 'svelte-multiselect'

  const genreTags = {label: "Genre", options: [`Rock`, `Electronic`, `Opera`]}
  const keyTags = {label: "Key", options: [`C`, `D`, `E`, `F`, `G`, `A`, `B`]}
  const scaleTags = {label: "Scale", options: [`Major`, `Minor`]}

  let selectedTags = []
</script>

<MultiSelect
  bind:selected
  options={[genreTags, keyTags, scaleTags]}
  maxSelect={[null, 1, 1]}
  required={[true, true, false] }
  allowUserOptions={ [true, false, true] } 
  placeholder="Select Tags"
/>
  1. I'm not sure I can see a strong use case for this

lysdexic-audio avatar Oct 17 '22 22:10 lysdexic-audio

  1. Let's go with disabling allowUserOptions entirely when options are grouped for now.
  2. Fair point. We'll stick with a single defaultDisabledTitle for all groups.

As I said, happy to take a PR for this. Though the default way to group options should be an object of arrays imo:

<script>
  import MultiSelect from 'svelte-multiselect'

  const options: Record<string, Option[]> = {
    Genre: [`Rock`, `Electronic`, `Opera`],
    Key: [`C`, `D`, `E`, `F`, `G`, `A`, `B`],
    Scale: [`Major`, `Minor`],
  }

  let selected = []
</script>

<MultiSelect
  bind:selected
  {options}
  maxSelect={[null, 1, 1]}
  required={[true, true, false]}
  allowUserOptions={[true, false, true]}
  placeholder="Select Tags"
/>

We can expand to

options: Record<string, { label: string, options: Option[], required: boolean, maxSelect: number | null }>

later.

janosh avatar Oct 17 '22 23:10 janosh

Sorry @janosh bit too pressured at work to get onto doing this properly - working around it for now. Anyone else wants to jump in please do

lysdexic-audio avatar Nov 07 '22 02:11 lysdexic-audio