Hi there!
I’m trying to build a custom select box, but I don’t know how to connect it properly to Live View.
I am using Alpine.js to keep track of the open state of the dropdown/select box, along with a state for the selected item.
Without adding much styling, the first draft looks something like this:
<.form for={@form} phx-change="validate" phx-submit="submit" phx-target={@myself}>
<div
x-data="{ open: false, selectedLabel: '', selectedKey: '' }"
@click.away="open = false"
class="relative"
>
<input type="hidden" name="select" x-model="selectedKey" />
<!-- Button -->
<button @click="open = !open" type="button">
<span
class="max-w-[120px] overflow-hidden"
x-text="selectedLabel === '' ? 'Select an option' : selectedLabel"
>
</span>
</button>
<!-- Menu -->
<div x-show="open" class="absolute z-10 mt-2 rounded border bg-white" x-cloak>
<ul class="max-h-[140px] overflow-auto [&>li]:cursor-pointer [&>li]:px-4 [&>li]:py-2 [&>li]:text-gray-500 hover:[&>li]:bg-gray-100">
<li
:for={{label, key} <- @options}
@click={"selectedLabel = '#{label}'; selectedKey = '#{key}'; open = false;"}
value={key}
>
<%= label %>
</li>
</ul>
</div>
</div>
</.form>
I have tried to use a hidden input with Alpine’s x-model
attribute to copy the selected value from the list to a real form element. When I submit the form, the select
value from the hidden input is available in the form parameters, but even though the value of the hidden input changes when an element is selected, the validate
event never fires.
Also, I think there must be a better way to build a custom select than copying the alpine state into a hidden input and managing state at multiple places…
Do you guys have any (simple) examples of how to build a custom select box? Btw, my goal is to add search to it.
Any advice would be appreciated!