Corex.Combobox
(Corex v0.1.0-alpha.33)
View Source
Phoenix implementation of Zag.js Combobox.
Minimal
<.combobox
class="combobox"
translation={%Corex.Combobox.Translation{placeholder: "Select a country", empty: "No results"}}
collection={[
%{label: "France", id: "fra", disabled: true},
%{label: "Belgium", id: "bel"},
%{label: "Germany", id: "deu"},
%{label: "Netherlands", id: "nld"},
%{label: "Switzerland", id: "che"},
%{label: "Austria", id: "aut"}
]}
>
<:trigger>
<.heroicon name="hero-chevron-down" />
</:trigger>
</.combobox>Grouped
<.combobox
class="combobox"
translation={%Corex.Combobox.Translation{placeholder: "Select a country", empty: "No results"}}
collection={[
%{label: "France", id: "fra", group: "Europe"},
%{label: "Belgium", id: "bel", group: "Europe"},
%{label: "Germany", id: "deu", group: "Europe"},
%{label: "Netherlands", id: "nld", group: "Europe"},
%{label: "Switzerland", id: "che", group: "Europe"},
%{label: "Austria", id: "aut", group: "Europe"},
%{label: "Japan", id: "jpn", group: "Asia"},
%{label: "China", id: "chn", group: "Asia"},
%{label: "South Korea", id: "kor", group: "Asia"},
%{label: "Thailand", id: "tha", group: "Asia"},
%{label: "USA", id: "usa", group: "North America"},
%{label: "Canada", id: "can", group: "North America"},
%{label: "Mexico", id: "mex", group: "North America"}
]}
>
<:trigger>
<.heroicon name="hero-chevron-down" />
</:trigger>
</.combobox>Extended
This example requires the installation of Flagpack to display the use of custom item rendering.
<.combobox
class="combobox"
translation={%Corex.Combobox.Translation{placeholder: "Select a country", empty: "No results"}}
collection={[
%{label: "France", id: "fra"},
%{label: "Belgium", id: "bel"},
%{label: "Germany", id: "deu"},
%{label: "Netherlands", id: "nld"},
%{label: "Switzerland", id: "che"},
%{label: "Austria", id: "aut"}
]}
>
<:item :let={item}>
<Flagpack.flag name={String.to_atom(item.id)} />
{item.label}
</:item>
<:trigger>
<.heroicon name="hero-chevron-down" />
</:trigger>
<:clear_trigger>
<.heroicon name="hero-backspace" />
</:clear_trigger>
<:item_indicator>
<.heroicon name="hero-check" />
</:item_indicator>
</.combobox>Extended Grouped
This example requires the installation of Flagpack to display the use of custom item rendering.
<.combobox
class="combobox"
translation={%Corex.Combobox.Translation{placeholder: "Select a country", empty: "No results"}}
collection={[
%{label: "France", id: "fra", group: "Europe"},
%{label: "Belgium", id: "bel", group: "Europe"},
%{label: "Germany", id: "deu", group: "Europe"},
%{label: "Japan", id: "jpn", group: "Asia"},
%{label: "China", id: "chn", group: "Asia"},
%{label: "South Korea", id: "kor", group: "Asia"}
]}
>
<:item :let={item}>
<Flagpack.flag name={String.to_atom(item.id)} />
{item.label}
</:item>
<:trigger>
<.heroicon name="hero-chevron-down" />
</:trigger>
<:clear_trigger>
<.heroicon name="hero-backspace" />
</:clear_trigger>
<:item_indicator>
<.heroicon name="hero-check" />
</:item_indicator>
</.combobox>Phoenix Form Integration
Use field={f[:key]} or field={@form[:key]} with a form built from an Ecto changeset. Set the form id with Corex.Form.get_form_id/1. Build the form in the controller with Schema.changeset(%Schema{}, %{}) |> Phoenix.Component.to_form(as: :form_name, id: "form-id"). In Live view add controlled mode and use the same changeset pattern. See the Select or NumberInput component docs for the full Controller and Live View examples.
Server-side Filtering
Disable client filtering with disabled={false} and use on_input_value_change to filter on the server. This example uses a local list; replace with a database query for real apps.
defmodule MyAppWeb.CountryCombobox do
use MyAppWeb, :live_view
@items [
%{id: "fra", label: "France"},
%{id: "bel", label: "Belgium"},
%{id: "deu", label: "Germany"},
%{id: "usa", label: "USA"},
%{id: "jpn", label: "Japan"}
]
def mount(_params, _session, socket) do
{:ok, assign(socket, items: [])}
end
def handle_event("search", %{"value" => value, "reason" => "input-change"}, socket) do
filtered =
if byte_size(value) < 1 do
[]
else
term = String.downcase(value)
Enum.filter(@items, fn item ->
String.contains?(String.downcase(item.label), term)
end)
end
{:noreply, assign(socket, items: filtered)}
end
def render(assigns) do
~H"""
<.combobox
id="country-combobox"
collection={@items}
filter={false}
on_input_value_change="search"
>
<:trigger><.heroicon name="hero-chevron-down" /></:trigger>
</.combobox>
"""
end
endStyling
Use data attributes to target elements:
[data-scope="combobox"][data-part="root"] {}
[data-scope="combobox"][data-part="control"] {}
[data-scope="combobox"][data-part="input"] {}
[data-scope="combobox"][data-part="trigger"] {}
[data-scope="combobox"][data-part="clear-trigger"] {}
[data-scope="combobox"][data-part="content"] {}
[data-scope="combobox"][data-part="empty"] {}
[data-scope="combobox"][data-part="item-group"] {}
[data-scope="combobox"][data-part="item-group-label"] {}
[data-scope="combobox"][data-part="item"] {}
[data-scope="combobox"][data-part="item-text"] {}
[data-scope="combobox"][data-part="item-indicator"] {}If you wish to use the default Corex styling, you can use the class combobox on the component.
This requires to install Mix.Tasks.Corex.Design first and import the component css file.
@import "../corex/main.css";
@import "../corex/tokens/themes/neo/light.css";
@import "../corex/components/combobox.css";You can then use modifiers
<.combobox class="combobox combobox--accent combobox--lg" collection={[]}>
<:empty>No results</:empty>
<:trigger>
<.heroicon name="hero-chevron-down" />
</:trigger>
</.combobox>Learn more about modifiers and Corex Design
Summary
Components
Renders a combobox component.
Components
Renders a combobox component.
Attributes
id(:string) - The id of the combobox, useful for API to identify the combobox.collection(:list) - The collection of items to display in the combobox. Defaults to[].controlled(:boolean) - Whether the combobox is controlled. Defaults tofalse.on_open_change(:string) - The server event name to trigger on open change. Defaults tonil.on_open_change_client(:string) - The client event name to trigger on open change. Defaults tonil.bubble(:boolean) - Whether the client events are bubbled. Defaults tofalse.disabled(:boolean) - Whether the combobox is disabled. Defaults tofalse.open(:boolean) - Whether the combobox is open. Defaults tofalse.value(:list) - The value of the combobox. Defaults to[].translation(Corex.Combobox.Translation) - Override translatable strings. Defaults tonil.always_submit_on_enter(:boolean) - Whether to always submit on enter. Defaults tofalse.auto_focus(:boolean) - Whether to auto focus the combobox. Defaults tofalse.close_on_select(:boolean) - Whether to close the combobox on select. Defaults totrue.dir(:string) - The direction of the combobox. When nil, derived from document (html lang + config :rtl_locales). Defaults tonil.input_behavior(:string) - The input behavior of the combobox. Defaults to"autohighlight".loop_focus(:boolean) - Whether to loop focus the combobox. Defaults tofalse.multiple(:boolean) - Whether to allow multiple selection. Defaults tofalse.invalid(:boolean) - Whether the combobox is invalid. Defaults tofalse.name(:string) - The name of the combobox.form(:string) - The id of the form of the combobox.read_only(:boolean) - Whether the combobox is read only. Defaults tofalse.required(:boolean) - Whether the combobox is required. Defaults tofalse.filter(:boolean) - When true, filter options client-side by input value. Set to false when using on_input_value_change for server-side filtering. Defaults totrue.on_input_value_change(:string) - The server event name to trigger on input value change. Defaults tonil.on_value_change(:string) - The server event name to trigger on value change. Defaults tonil.positioning(:map) - The positioning of the combobox. Defaults to%Corex.Positioning{hide_when_detached: true, strategy: "fixed", placement: "bottom", gutter: 8, shift: 0, overflow_padding: 0, arrow_padding: 4, flip: true, slide: true, overlap: false, same_width: true, fit_viewport: false}.field(Phoenix.HTML.FormField) - A form field struct retrieved from the form, for example: @form[:country]. Automatically sets id, name, value, and errors from the form field.errors(:list) - List of error messages to display. Defaults to[].- Global attributes are accepted.
Slots
label- The label content. Accepts attributes:class(:string)
empty- Content when there are no results. When omitted, translation.empty is used. Accepts attributes:class(:string)
trigger(required) - The trigger button content. Accepts attributes:class(:string)
clear_trigger- The clear button content. Accepts attributes:class(:string)
item_indicator- Optional indicator for selected items. Accepts attributes:class(:string)
error- Accepts attributes:class(:string)
item- Custom content for each item. Receives the item as :let binding. Accepts attributes:class(:string)