Skip to main content

Combobox i ren HTML

Denne siden forklarer i detalj hvordan <ix-combobox> fungerer når du skriver ren HTML, Astro eller et annet ikke-React-miljø. Bruker du React, holder det å lese Combobox, der hele strukturen er skjult bak Combobox-komponenten. For bruk, tilstander og API, se hovedsiden.

Combobox er en ARIA-lim-komponent: web-komponenten eier ikke innholdet, den binder sammen native elementer du skriver selv. Du er ansvarlig for strukturen (input, liste, alternativer); komponenten legger på ARIA, håndterer tastatur og filtrering, posisjonerer lista, og synkroniserer valget til et skjult <select>. Det betyr at du har full kontroll på markup, men også at du må skrive litt mer enn for en vanlig <select>.

Anatomi

Et fullstendig combobox-markup ser slik ut. Hver del har en fast rolle:

<ix-combobox class="ix-combobox" name="land" data-no-hits-text="Ingen treff">
<div class="ix-combobox__chips" data-field="chips"></div>
<div class="ix-text-field">
<input class="ix-text-field__input" />
<button type="button" class="ix-combobox__toggle" aria-label="Vis alternativer"></button>
</div>
<div class="ix-combobox__listbox" hidden>
<div class="ix-combobox__option" data-value="47">
<span class="ix-combobox__option-check" aria-hidden="true"></span>
<span class="ix-combobox__option-label">Norge</span>
<span class="ix-combobox__option-description">+47</span>
</div>
<!-- flere alternativer … -->
</div>
<div class="ix-combobox__no-hits" role="status" hidden>Ingen treff</div>
<select data-field="native" name="land" hidden></select>
</ix-combobox>
DelRolle
<ix-combobox name="…">Rot-elementet. name blir navnet på det skjulte <select> ved skjemainnsending
[data-field="chips"]Wrapper for chips. Kun flervalg — la den stå tom, komponenten fyller den
.ix-text-field > inputSøkefeltet brukeren skriver i. Får role="combobox" og all input-ARIA
.ix-combobox__toggleChevron-knappen som åpner/lukker lista
.ix-combobox__listboxLista med alternativene. Skriv den hidden — komponenten styrer synlighet
.ix-combobox__option[data-value]Ett alternativ. data-value er verdien
.ix-combobox__option-labelDen synlige teksten for alternativet
.ix-combobox__option-descriptionValgfri andrelinje under label
.ix-combobox__no-hitsMelding når filteret gir 0 treff (role="status")
select[data-field="native"]Skjult <select> som faktisk sendes med skjemaet. Kan utelates — opprettes da automatisk

Legg merke til at alternativet ikke er et <option>-element, men en <div class="ix-combobox__option">. Verdien ligger i data-value, ikke i tekstinnholdet. Det er dette som lar et alternativ ha to linjer (label + beskrivelse) og en checkmark, noe et native <option> ikke kan.

Hvordan et valg skjer

Når brukeren velger et alternativ (klikk eller Enter), gjør komponenten alt dette for deg:

  1. Setter aria-selected="true" på den valgte .ix-combobox__option. Dette er sannhetskilden for hva som er valgt.
  2. I single: skriver alternativets label inn i inputfeltet. I flervalg: lager en chip i [data-field="chips"] og tømmer inputfeltet.
  3. Bygger det skjulte <select> på nytt fra alle options som har aria-selected="true". Hver blir en <option value="<data-value>" selected>.
  4. Fyrer en change-hendelse på <ix-combobox>.

Du håndterer altså aldri chips, inputtekst eller den skjulte selecten manuelt. Alt følger av aria-selected på options. Det samme gjelder når brukeren fjerner et valg (avmarkerer, eller sletter en chip): aria-selected settes til false, chip/inputtekst fjernes, og selecten bygges på nytt.

Forhåndsvalgte verdier

Skal ett eller flere alternativer være valgt når siden lastes, markerer du dem med aria-selected="true".ix-combobox__option. Det er den eneste sanningskilden for startverdi:

  • Ikke sett value på inputen. Komponenten fyller den selv fra det forhåndsvalgte alternativet.
  • Ikke skriv <option selected> i det skjulte selectet. Det bygges opp på nytt fra aria-selected hver gang og overskrives.
  • Ikke skriv chips (<data class="ix-chip">) for hånd. Komponenten genererer dem.

Single med ett forhåndsvalg

Laster...

Norge vises i feltet fra start fordi optionen har aria-selected="true". Ingenting annet er nødvendig.

Flervalg med flere forhåndsvalg

I flervalg gir du hvert forhåndsvalgt alternativ aria-selected="true" og lar [data-field="chips"] stå tom. Komponenten lager en chip per valgte alternativ.

Laster...

Form-innsending

Combobox er ikke selv et form-felt. Den synkroniserer valget til et skjult <select data-field="native">, og det er selecten som sendes med skjemaet:

  • name på selecten arves fra <ix-combobox name="…">.
  • Hver valgte option blir en <option value="<data-value>" selected>.
  • I flervalg settes multiple på selecten automatisk, så alle valgte verdier sendes.

Utelater du selecten, oppretter komponenten den automatisk. Legger du den til selv, la den stå tom. Komponenten fyller den. (Å skrive den selv er nyttig hvis du vil styre nøyaktig hvor i skjemaet den ligger.)

<form>
<ix-combobox name="land"></ix-combobox>
<button type="submit">Send</button>
</form>

Ved innsending sendes land=47 i single, eller land=47&land=46 i flervalg, samme som en vanlig <select> / <select multiple>.

Reagere på endringer med JavaScript

Uten React lytter du på change-hendelsen på <ix-combobox> og leser gjeldende verdi fra det skjulte <select>, som allerede er synkronisert når hendelsen fyres.

const combobox = document.querySelector('ix-combobox');
const select = combobox.querySelector('select[data-field="native"]');

combobox.addEventListener('change', () => {
// Single: én verdi. Flervalg: bruk select.selectedOptions.
console.log('Valgt:', select.value);

// Flervalg — alle valgte verdier:
const alle = Array.from(select.selectedOptions, (o) => o.value);
console.log('Alle valgte:', alle);
});

change er et bublende CustomEvent uten detail. Verdien ligger i det skjulte <select>, ikke på hendelsen.

Hva ix-combobox gjør med DOM-en

Du skriver den semantiske strukturen. Komponenten legger på ARIA og IDer. Her er hva som skjer i single-varianten, fra HTML du skriver til DOM etter at komponenten har kjørt.

Før (det du skriver):

<ix-combobox class="ix-combobox" data-no-hits-text="Ingen treff" name="land">
<div class="ix-text-field">
<input class="ix-text-field__input" aria-label="Land" />
<button type="button" class="ix-combobox__toggle" aria-label="Vis alternativer"></button>
</div>
<div class="ix-combobox__listbox">
<div class="ix-combobox__option" data-value="47" aria-selected="true">
<span class="ix-combobox__option-check" aria-hidden="true"></span>
<span class="ix-combobox__option-label">Norge</span>
</div>
</div>
<div class="ix-combobox__no-hits" role="status">Ingen treff</div>
</ix-combobox>

Etter (det som er i DOM etter at ix-combobox har kjørt):

<ix-combobox class="ix-combobox" data-no-hits-text="Ingen treff" name="land">
<div class="ix-text-field">
<input class="ix-text-field__input" aria-label="Land"
id="ix-combobox-input-1" role="combobox" aria-autocomplete="list"
autocomplete="off" aria-expanded="false"
aria-controls="ix-combobox-listbox-1" />
<button type="button" class="ix-combobox__toggle" aria-label="Vis alternativer" tabindex="-1"></button>
</div>
<div class="ix-combobox__listbox" id="ix-combobox-listbox-1"
role="listbox" aria-multiselectable="false" hidden>
<div class="ix-combobox__option" data-value="47" aria-selected="true"
id="ix-combobox-listbox-1-option-0" role="option">
<span class="ix-combobox__option-check" aria-hidden="true"></span>
<span class="ix-combobox__option-label">Norge</span>
</div>
</div>
<div class="ix-combobox__no-hits" role="status"></div>
<!-- Opprettet automatisk, fylt fra aria-selected: -->
<select data-field="native" name="land" hidden>
<option value="47" selected>Norge</option>
</select>
</ix-combobox>

Fordi Norge-optionen hadde aria-selected="true", satte komponenten i tillegg input.value = "Norge" og la til <option value="47" selected> i det skjulte selectet.

Hva som ble lagt til:

HvaHvorHvorfor
role="combobox", aria-autocomplete="list"<input>Gjør feltet til en combobox for skjermlesere
id (genereres om den mangler)<input>, .ix-combobox__listbox, hver .ix-combobox__optionGrunnlag for ARIA-koblinger og virtual focus
aria-controls<input>Peker på listbox-IDen
aria-expanded<input>true/false når lista åpnes/lukkes
aria-activedescendant<input>Peker på aktivt alternativ under piltast-navigasjon — fokus flyttes aldri fysisk inn i lista
role="listbox", aria-multiselectable.ix-combobox__listboxSemantikk for lista; true i flervalg
role="option", aria-selectedhver .ix-combobox__optionSemantikk og valgt-tilstand (aria-selected="false" settes om den mangler)
tabindex="-1".ix-combobox__toggleChevron-knappen skal ikke ha eget tab-stopp — feltet betjenes fra inputen
<select data-field="native">inni <ix-combobox>Skjult select for form-innsending. Opprettes automatisk om du ikke skrev den, og fylles fra aria-selected

I flervalg legger komponenten i tillegg til aria-description på inputen (fra data-arrow-hint-text) og genererer <data class="ix-chip" data-removable>-elementer i [data-field="chips"] for hvert valgte alternativ.

Relatert

  • Combobox — bruk, tilstander, React-API og props
  • Select — enklere valg fra kort/mellomlang liste uten søk