RizzyUI

Combobox

The RzCombobox is a robust, autocomplete-enabled select component powered by Tom Select. It supports single and multiple selections, asynchronous loading, option grouping, rich templating, and plugin extensibility, all while maintaining native form compatibility through a server-rendered native <select> fallback that remains the form-post source of truth.

Accessibility contract: the component renders a labeled native select in SSR output and then enhances it in-place with Tom Select. Label, description, and validation relationships are preserved on the enhanced control, keyboard behavior follows Tom Select defaults (Arrow keys, Enter, Escape, Backspace, and typeahead), and CSP-safe inert JSON configuration is used for initialization.

Basic Single Select

A standard single-select dropdown bound to a list of strings.

Source
<div x-data="comboboxBasicDemo"
     data-initial-selected="@(_model.Fruit ?? "None")"
     x-on:rz:combobox:change="handleComboboxChange">
    <RzCombobox TItem="string" TValue="string"
                Items="@_fruits"
                @bind-Value="_model.Fruit"
                For="@(() => _model.Fruit)"
                Placeholder="Pick a fruit..." />

    <div class="mt-4 text-sm text-muted-foreground">
        Selected: <strong x-text="selectedFruit">@(_model.Fruit ?? "None")</strong>
    </div>
</div>

<script>
    // site.js controller:
    // handleComboboxChange(event) { this.selectedFruit = event.detail?.text || 'None'; }
</script>

Multiple Selection

Enable multiple selection by setting Multiple="true". The remove_button and checkbox_options plugins are automatically enabled for better UX.

Source
<RzCombobox TItem="string" TValue="IEnumerable<string>"
            Items="@_skills"
            Multiple="true"
            @bind-Value="_model.Skills"
            For="@(() => _model.Skills)" />

Binding to Objects

Bind to complex objects by specifying ValueSelector (what is stored) and TextSelector (what is displayed). Here we bind to the Id (int) of a Person object.

Source
<RzCombobox TItem="UserData" TValue="int?"
            Items="@_users"
            ValueSelector="@(u => u.Id.ToString())"
            TextSelector="@(u => u.Name)"
            @bind-Value="_model.AssigneeId" />

Option Grouping

RzCombobox natively supports SelectListItem grouping.

Source
// Setup SelectListItems with Groups
var frontendGroup = new SelectListGroup { Name = "Frontend" };
var backendGroup = new SelectListGroup { Name = "Backend" };

_groupedItems = [
    new SelectListItem("React", "react") { Group = frontendGroup },
    new SelectListItem("Vue", "vue") { Group = frontendGroup },
    new SelectListItem(".NET", "dotnet") { Group = backendGroup },
    new SelectListItem("Django", "django") { Group = backendGroup },
];

Item Creation (Tags)

Allow users to create new items on the fly by setting Create="true" in the options.

Source
<RzCombobox Items="@_tags"
            Multiple="true"
            Options="@(new ComboboxOptions { Create = true })"
            @bind-Value="_model.Tags" />

Plugins: Clear Button

Easily extend functionality using plugins. Here we add a 'Clear' button to a single-select input.

Source
private ComboboxOptions _clearButtonOptions = new()
{
    Plugins = new List<IComboboxPlugin> { new ComboboxClearButtonPlugin() }
};

Custom Templates

Customize how options and selected items are rendered using OptionTemplate and ItemTemplate. Alpine.js syntax is used within the template, with access to the item object.

Source
<EditForm Model="@_model">
    <Field>
        <Label>Select User</Label>
        <RzCombobox TItem="UserData" TValue="int?"
                    Items="@_users"
                    ValueSelector="@(u => u.Id.ToString())"
                    TextSelector="@(u => u.Name)"
                    Value="_model.AssigneeId"
                    For="@(() => _model.AssigneeId)"
                    Placeholder="Search users...">
            <OptionTemplate>
                <div class="flex items-center gap-3 py-1">
                    <div class="flex items-center justify-center size-8 rounded-full bg-secondary text-secondary-foreground">
                        <RzAvatar Size="Size.Small">
                            <AvatarImage :src="item.photo"/>
                        </RzAvatar>
                    </div>
                    <div class="flex flex-col">
                        <span class="font-medium text-sm" x-text="item.name"></span>
                        <span class="text-xs text-muted-foreground" x-text="item.email"></span>
                    </div>
                </div>
            </OptionTemplate>
        </RzCombobox>
    </Field>
</EditForm>

Max Items Limit

Restrict the number of selections in multi-select mode. Here, you can only select up to 2 items.

Accessibility

RzCombobox<TItem, TValue> uses an SSR-first strategy: the server renders a native <select> that carries label, description, validation, and disabled semantics; Tom Select then enhances the control in place. This preserves form posting behavior while providing richer keyboard and search UX.

Template guidance: keep OptionTemplate and ItemTemplate content text-inclusive and avoid icon-only rows so screen readers announce meaningful option names. Disabled options remain non-selectable in both fallback and enhanced modes.

CSP note: the component initializes from inert JSON in a script type="application/json" block and loads assets through RizzyUI's CSP-safe loader, so no inline executable script is required.

KeyBehavior
ArrowDown / ArrowUpMove through filtered options in the open list.
EnterCommit the active option to the underlying select value.
EscapeCloses the open dropdown without forcing focus away from the control.
BackspaceIn multi-select mode, removes prior selected tokens when the search box is empty.
TypeaheadFilters available options using Tom Select's search behavior.

Automated coverage lives in RzComboboxTests (SSR fallback/configuration) and tests/accessibility/combobox.a11y.spec.ts (enhanced keyboard/search/re-init behavior).

Component Parameters

The following table summarizes the core parameters on RzCombobox<TItem, TValue>.

PropertyDescriptionTypeDefault
ItemsData source used to populate options.IEnumerable<TItem>Empty
OptionsTom Select configuration options.ComboboxOptionsnew()
MultipleEnables multi-select mode.boolfalse
PlaceholderPlaceholder text shown when no value is selected.string?Localized default
ValueSelectorMaps an item to the stored option value.Func<TItem, string>?Auto for SelectListItem
TextSelectorMaps an item to display text.Func<TItem, string>?Auto for SelectListItem
OptionTemplateCustom template for dropdown options.RenderFragment?null
ItemTemplateCustom template for selected item rendering.RenderFragment?null

Alpine API

The combobox client behavior is provided by Alpine x-data component rzCombobox and exposes state + events for SSR-safe browser integration.

Alpine State

PropertyTypeDescription
valuestring | string[]Current selected value for single-select comboboxes, or the selected values array for multiple-select comboboxes.
valuesstring[]Current selected values as an array of strings.
textstringCurrent selected display text for single-select comboboxes, or comma-separated selected display text for multiple-select comboboxes.
textsstring[]Current selected display texts as an array of strings.
tomSelectTomSelect | nullThe underlying Tom Select instance after initialization.

Alpine Methods

MethodParametersDescription
initTomSelectNoneCreates and configures the Tom Select instance.
syncSelectedStateemit = trueSynchronizes value, values, text, and texts from Tom Select/native select state and dispatches change event when enabled.
getOptionTextvalueResolves display text from Tom Select options, with native select fallback.

Browser Event

rz:combobox:change is the supported SSR/browser-side integration point for reacting to combobox changes without Blazor interactivity.

Source
{ id, selectId, name, multiple, value, values, text, texts }