Varendo

Combobox

Searchable choice with APG behavior; stale remote options cannot overwrite current input.

FamilyinputLicenseApache-2.0
StandaloneAvailable

Use the web element directly without the semantic runtime.

Semantic bindingAvailable

A registered presentation adapter can bind this component to host-owned meaning and state.

Automatic adaptationNo standard recipe

The standard recipe resolver does not select this component automatically.

Import and live example

One open person combobox with a query draft and bounded options.

Interactive preview requires JavaScript.

View the complete example source
import {registerAeliqoElements} from "@varendo/web";
import {
  AeliqoCheckboxElement,
  AeliqoComboboxElement,
  AeliqoDateFieldElement,
  AeliqoDateRangeElement,
  AeliqoFieldGroupElement,
  AeliqoFileInputElement,
  AeliqoFormElement,
  AeliqoNumberFieldElement,
  AeliqoRadioGroupElement,
  AeliqoSearchFieldElement,
  AeliqoSelectElement,
  AeliqoSliderElement,
  AeliqoSwitchElement,
  AeliqoTextAreaElement,
  AeliqoTextFieldElement,
  type AeliqoOption,
} from "@varendo/web/inputs";

const options: readonly AeliqoOption[] = [
  {value: "ada", label: "Ada Lovelace", description: "Research"},
  {value: "grace", label: "Grace Hopper", description: "Product"},
  {value: "lin", label: "Lin Chen", disabled: true},
];

registerAeliqoElements();

const host = document.querySelector<HTMLElement>("#aeliqo-example") ?? (() => {
  const created = document.createElement("div");
  created.id = "aeliqo-example";
  (document.body ?? document.documentElement).append(created);
  return created;
})();

function createCatalogRoot(container: HTMLElement): HTMLElement {
  const root = document.createElement("div");
  root.dataset.catalogSourceRoot = "true";
  root.style.display = "grid";
  root.style.gap = "12px";
  container.append(root);
  return root;
}

function createCatalogElement<T extends HTMLElement>(tagName: string, container: HTMLElement): T {
  const element = document.createElement(tagName) as T;
  element.setAttribute("data-aeliqo-theme", "light");
  container.append(element);
  return element;
}

function appendSlottedText(root: HTMLElement, slot: string, textContent: string): void {
  const content = document.createElement("span");
  content.slot = slot;
  content.textContent = textContent;
  root.append(content);
}

const root = createCatalogRoot(host);
(((root) => {
		const element = createCatalogElement<AeliqoComboboxElement>("aeliqo-combobox", root);
		element.label = "Person";
		element.name = "person";
		element.options = options;
		element.value = "ada";
		element.query = "Ada";
		element.open = true;
		element.minQueryLength = 1;
	}))(root);

Purpose

A searchable choice field with separate local query and selected value properties. The host can set the selected value; typing clears it, while choosing an option updates it and emits a typed change. Late remote responses are ignored, so stale options do not replace current results; the host owns query sourcing and persistence.

When to use it

When to use a different component

Properties and defaults

query is a draft separate from the selected value. Supply bounded options or a host-owned optionsLoader; stale loader results are cancelled and ignored.

Properties, ownership, and initial values
PropertyUse and ownershipDeclared typeInitial value
labelProvides the visible label and accessible name for the component.string''
descriptionProvides supporting text associated with the control or value.string''
errorProvides the current validation or operation error associated with the control.string''
requiredMarks the control as required for validation and native accessibility semantics.booleanfalse
disabledPrevents user interaction while keeping the control and its current value visible.booleanfalse
readOnlyKeeps the current value focusable and readable while preventing edits.booleanfalse
nameProvides the stable form or action name used by the host to identify this control.string''
autocompletePasses an autocomplete purpose to the native input so browsers can offer an appropriate saved value.string'off'
localeSelects locale-sensitive formatting and parsing behavior.string'en-US'
validationStateControls the current idle, pending, valid, or invalid validation state.AeliqoValidationState'idle'
validatorRuns host-provided synchronous validation for a proposed input value.AeliqoValidator<T> | undefinedundefined
optionsSupplies the complete bounded choice list, including stable values, labels, descriptions, and disabled states.readonly AeliqoOption[][]
optionsLoaderLoads bounded combobox options for the current query. The host owns cancellation, authorization, and failures.AeliqoOptionsLoader | undefinedundefined
valueControls the current value. Apply accepted user proposals back to this property.string''
defaultValueProvides the initial uncontrolled value. Later updates come from component interaction.string''
querySupplies the current search or combobox query independently from a committed selection.string''
placeholderProvides a short input hint when the current draft is empty; it does not replace a visible label.string''
openControls whether the overlay or expandable surface is currently open.booleanfalse
minQueryLengthSets the number of query characters required before a combobox query proposal is useful.number0

Events

Events, payloads, timing, and application responsibilities
EventPayloadEmittedApplication responsibility
aeliqo-input-change{source, value, composing?}Whenever the user proposes a draft value change.Validate or store the draft and reassign controlled value or checked state.
aeliqo-combobox-query{source, query}While the user edits the combobox query.Cancel obsolete loads, fetch authorized bounded options, and update options.
aeliqo-validation{source, state, message}When validation enters pending, valid, or invalid state.Merge the result with application validation and display authoritative errors.

Events cross the component boundary as user proposals. Validate their detail and current authority before applying a business effect.

Listen for aeliqo-input-change

TypeScript example
const element = document.querySelector('aeliqo-combobox');<p>element?.addEventListener('aeliqo-input-change', (event) => {
  const proposal = (event as CustomEvent<unknown>).detail;
  // Validate the proposal, update host state, then assign controlled properties.
  applyProposal(proposal);
});

Listen for aeliqo-combobox-query

TypeScript example
const element = document.querySelector('aeliqo-combobox');</p>
<p>element?.addEventListener('aeliqo-combobox-query', (event) => {
  const proposal = (event as CustomEvent<unknown>).detail;
  // Validate the proposal, update host state, then assign controlled properties.
  applyProposal(proposal);
});

Listen for aeliqo-validation

TypeScript example
const element = document.querySelector('aeliqo-combobox');</p>
<p>element?.addEventListener('aeliqo-validation', (event) => {
  const proposal = (event as CustomEvent<unknown>).detail;
  // Validate the proposal, update host state, then assign controlled properties.
  applyProposal(proposal);
});

States and failure handling

Relevant states:

Expected result: The query and selected identity remain distinct while the list stays bounded.

Changing value or replacing validator cancels validation for the previous value and clears its validator-owned error. An independently supplied host error survives the change. Late results after a reset or disconnect are ignored.

With a static options array, the component filters the bounded list as the query changes. optionsLoader(query, signal) is the optional remote path: the host owns the request and its authorization, while the component aborts the previous load and ignores an older completion. At most 500 options are accepted. A loader failure keeps the field visible, reports “Options could not be loaded”, and never commits a different value. minQueryLength delays loading until enough characters are typed.

Keyboard, focus, and accessibility

Keyboard behavior:

Exposed semantics:

Responsive behavior

Keep the query draft and selected value distinct at narrow widths. Test long option names against the visible viewport.

Style hooks

Performance limits

Generated TypeScript declaration

View generated declaration
export declare class AeliqoComboboxElement extends AeliqoFieldElement<string> {
    static readonly properties: {
        label: {
            type: StringConstructor;
        };
        description: {
            type: StringConstructor;
        };
        error: {
            type: StringConstructor;
        };
        required: {
            type: BooleanConstructor;
            reflect: boolean;
        };
        disabled: {
            type: BooleanConstructor;
            reflect: boolean;
        };
        readOnly: {
            attribute: string;
            type: BooleanConstructor;
            reflect: boolean;
        };
        name: {
            type: StringConstructor;
            reflect: boolean;
        };
        autocomplete: {
            type: StringConstructor;
        };
        locale: {
            type: StringConstructor;
        };
        validationState: {
            attribute: string;
            type: StringConstructor;
            reflect: boolean;
        };
        validator: {
            attribute: boolean;
        };
        options: {
            attribute: boolean;
        };
        optionsLoader: {
            attribute: boolean;
        };
        value: {
            type: StringConstructor;
            reflect: boolean;
        };
        defaultValue: {
            attribute: string;
            type: StringConstructor;
        };
        query: {
            type: StringConstructor;
        };
        placeholder: {
            type: StringConstructor;
        };
        open: {
            type: BooleanConstructor;
            reflect: boolean;
        };
        minQueryLength: {
            attribute: string;
            type: NumberConstructor;
        };
    };
    options: readonly AeliqoOption[];
    optionsLoader: AeliqoOptionsLoader | undefined;
    value: string;
    defaultValue: string;
    query: string;
    placeholder: string;
    open: boolean;
    minQueryLength: number;
    private activeIndex;
    private loadSequence;
    private loadAbort;
    private composing;
    private suppressTrailingCompositionInput;
    connectedCallback(): void;
    protected willUpdate(changed: Map<PropertyKey, unknown>): void;
    protected updated(changed: Map<PropertyKey, unknown>): void;
    protected isCurrentValidationValue(value: string): boolean;
    disconnectedCallback(): void;
    protected resetField(): void;
    protected render(): import("lit").TemplateResult<1>;
    private activeOptionId;
    private isInvalidSelection;
    private renderOptionList;
    private renderOption;
    focus(options?: FocusOptions): void;
    get loading(): boolean;
    private readonly handleFocus;
    private readonly handleBlur;
    private readonly handleInput;
    private readonly handleKeyDown;
    private handleArrowKey;
    private handleEscapeKey;
    private handleEnterKey;
    private choose;
    private readonly handleCompositionStart;
    private readonly handleCompositionEnd;
    private commitQueryInput;
    private loadForQuery;
    private safeOptions;
    private filteredOptions;
    private labelForValue;
    private displayQuery;
    private firstEnabledIndex;
    private nextEnabledIndex;
    private navigationStart;
    private native;
    private syncNative;
    private cancelLoader;
    static readonly styles: import("lit").CSSResult[];
}

Version

This page documents the Varendo 0.6 component contract.