LiveSelect - Dynamic selection input component for LiveView

thanks @linusdm

Not a good one unfortunately, no. You can use the options assign (only documented in master, but works also in the hex release) to pass an initial set of available options, but not an initial selection.
This will become possible when the issue you mentioned is resolved (I’m working on it)

Totally agree. It’s been on the back-burner for some time, I hope I’ll be able to get to it soon.

1 Like

Can you expand on how the options assign works? Is this a set of options that will always be there, regardless the text you’ve typed in the text input field? Or will it be replaced as soon as you trigger the hook that returns options? Or is this set of options somehow searched through, and mixed with the options that are returned dynamically? Sorry for the lazy question, I know it’s all in flux right now…

Hi @linusdm ! No worries, perfect timing in fact :slight_smile:

Is this a set of options that will always be there, regardless the text you’ve typed in the text input field? Or will it be replaced as soon as you trigger the hook that returns options?

The latter

I just finished the changes to enable setting an initial selection, either implicitly from the form or explicitly with the value option. It’s in master. Please try it out if you can. Any questions, comments, or bugs, please post them in the github issue. Thanks!

Published 0.3.3

  • set initial selection from the form or manually with value option
  • set initial list of available options with options option
  • add a max_selectable option to limit the maximum size of the selection

Also deployed showcase app at: https://live-select.fly.dev/ (thanks @linusdm for reminding me)

4 Likes

Thanks for this library, it looks great.

I’d like to try if as a tagging interface as in Tagging interface with Phoenix LiveView and Tailwind - Tagging part 2 - Tutorials and screencasts for Elixir, Phoenix and LiveView - but there’s something missing to my understanding.

Can the user enter new values by pressing enter? I think that’s not possible currently.

Can the user enter new values by pressing enter? I think that’s not possible currently.

Yes it’s possible. You can either use the arrow keys to navigate to the entry in the dropdown and hit enter - or you can click on the entry. You can test this in the showcase app.

Thanks, but I still think it’s not possible to add new entries that are not in the original options, please see this video I recorded:

Here, in :tags mode, I can enter “Seattle” and select it as it’s in the options, but if I want to add a new one, like “Monreal”, I can’t add it to the list. Am I missing something?

I think it’s a matter of using update_options with the text from the ChangeMsg via handle_info, or just live updating the options.

I’ll see if I can get that done from the examples, thanks.

Nope, you’re very much correct. You can’t currently add new entries not present in the options. I misunderstood your original question, sorry.

So it would be something like a “dynamic option mode”, where if you hit enter whatever you have typed will become a new selected option. I think this is an interesting use case, at least another person mentioned it during a conversation.

If you could create an issue on github with a short description, that would be great! I’m sure it won’t be hard to implement.

1 Like

Cool, I just created the issue Add new option dynamically · Issue #11 · maxmarcon/live_select · GitHub

Thanks!

1 Like

Version 0.4.0 is out

Here’s the new stuff:

  • a newavailable_option_class configuration option to style options that have not been selected yet
  • a new user_defined_options configuration option to allow users to enter any tag
  • ability to assign a custom id to the component
  • ability to programmatically clear the selection using the clear assign
  • a new allow_clear configuration option. If set, a tiny x button will appear in the text input in single selection mode. Clicking the button clears the selection.

LiveSelect.update_options/2 has been deprecated in favor of using LiveView.send_update/3 directly. This is the first step towards a planned version 1.0.0 , which will expose LiveSelect as a function component and use events instead of messages for the update loop. In this way it will be easier to use LiveSelect from within another live component, such as the form components created by the new phx.gen.live generators.

Thanks to @jaimeiniesta and @KristerV (plus 2 other GitHub users I can’t find here :slight_smile:) for their feedback and suggestions.

7 Likes

awesome! can’t wait for the events based approach.

i’m going to test this thing out again this week as i just really need it :smiley:

2 Likes

Version 1.0.0 is here :tada: :monkey:

Happy to announce this release. It’s been a lot of work, and I definitely fancy a little break from LV :laughing:, but I’m glad this is finally out!

Here’s the changes:

  1. Rendering using a (sexy, new) function component <.live_select /> instead of the (unsexy, old) function style <%= live_select ... %>
  2. Dropping the message-based update cycle (which used handle_info/2) in favour of an event-based update cycle (which uses handle_event/3). This makes it much easier and more intuitive to use LiveSelect from another LiveComponent.
  3. Ability to customize the default rendering of dropdown entries and tags using the :option and :tag slots

Change (2) is the most important one: folks who were using LiveSelect from a LiveComponent were annoyed because LiveSelect was using messages to request an update, and messages can’t be received by LiveComponents. This was forcing users to place the update logic in the LiveView and not in the LiveComponent where it would naturally reside. But now you can just do:

<.live_select form={form} field={field} mode={:tags} phx-target={@myself} />

and

def handle_event("live_select_change", %{"text" => text, "id" => live_select_id}, socket) do
   send_update(LiveSelect.Component, id: live_select_id, options: retrieve_options(text))
end

All in your LiveComponent (or LiveView), and you’re good.

I hope that folks who use LiveComponent-based forms will have a more pleasant experience now.

Change (3) is also kind of cool: you can now override rendering of tags and options using slots.
Say you want to add an icon to your tags or options. Now you can do:

<.live_select ...  >
        <:option :let={option}>
          <div class="flex">
            <.globe />&nbsp;<%= option.label %>
          </div>
        </:option>
        <:tag :let={option}>
            <.check />&nbsp;<%= option.label %>
        </:tag>
</.live_select>

which would result in this:

Thanks to anyone who provided feedback so far!

Cheers,
Max

13 Likes

Great changes, Max! Excited to give this a try.

1 Like

so nice. just updated. plays so well with my components (many of which are generated by phoenix).

thanks a lot! well deserved version number :slight_smile:

2 Likes

Thanks a lot @KristerV and @zachallaun for your kind comments! Much appreciated

Congratz with the 1.0.0 release! You certainly put a lot of effort in it. Thanks for contributing to the ecosystem. One day I’m sure I’ll get to this lib for a webapp I’ll build in the future :slight_smile:

2 Likes

Hi @trisolaran,
Firstly, kudos … your component has matured really nicely ! It is really well thought through and flexible.

I am trying to figure out one kink I am having around the “clickable” area for the options.
Here is how I am calling live_select -

      <.live_select
        form={f}
        field={:currency_code}
        placeholder="Select a Currency"
        update_min_len={1}
        style={:daisyui}
      >
        <:option :let={option}>
          <div class="flex">
            <img src={option.country_flag} class="avatar text-sm w-12 square" />
          </div>
        </:option>
      </.live_select>

The issue I am seeing is that the change event doesn’t fire on clicking the image (flag). It only fires when clicking on the blank space on the right of the flag. I have tried various options around styling (tailwind vs daisyui) as well as using block vs. flex. Behavior remains the same …

Updated : A bit more info - the content that is drawn from the :option slot appears to be obscuring the pointer behavior for the selected option. As long as I click outside the outlined content for the selected dropdown option, it works. Attaching a graphic also.
currency_selector

Any pointers ?

Hi @milangupta and thanks for the nice words.

Also thanks for finding this is bug, I was able to reproduce it.

I pushed a fix on main. Can you please try your application against the latest live_select’s main and let me know?

2 Likes

Unfortunately, still no luck. I made sure I was pointed to github main branch and that the changes reflected in my deps.

Here is a better picture … I put the “outline” tag around the custom option elements to show this more clearly. The option when hovered over greys out correctly. However, the selection does not fire if mouse is in the outlined box.
currency_selector

I was suspecting this is some css thing … was looking at z-index etc. It looks like the underlying element is the dropdown option with the registered click handler, however, the custom option elements from the slot are not within that / just overlayed.