Gå til hovedinnhold
KOMPONENTER

Dropdown

npmv5.3.1

Dropdown presenterer en liste over valg der brukeren kan velge ett av dem.

npm install @entur/dropdown
@import '@entur/dropdown/dist/styles.css';

Migrering fra v4 -> v5

Bruk

Dropdown og SearchableDropdown er komponenter som lar brukeren utføre ett valg blant mange ulike valgalternaltiver. Skal flere valg være mulig på en gang må du bruke MultiSelect. Komponenten viser frem en liste med valg bassert på items-prop-en, der items kan være en liste med string eller objekter med value, label og icons - eller en blanding av disse. For å dekke situasjoner der valgalternaltiver kommmer fra et API eller lignende støtter items også synkrone og asynkrone funksjoner som returnerer samme type liste som items aksepterer.

Kom i gang

Dropdown-ene har tre påkrevde props: label, items og selectedItem. I tillegg har den også onChange som ikke er påkrevd, men som er nødvendig for å gjøre komponenten interaktiv.

label er feltets navn og beskriver hva du velger. items tar inn listen med valgalternaltiver, se Liste med valgalternaltiver for mer info. selectedItem og onChange jobber sammen for å holde styr på state for valgt element. selectedItem skal være av typen NormalizedDropdownItemType eller null og onChange skal være en funksjon som tar inn et valgt element og oppdaterer verdien på selectedItem til dette elementet. Se Vanlig dropdown- og Søkbar dropdown-eksemplene for å se dette i praksis.

// Definition of NormalizedDropdownItemType
type NormalizedDropdownItemType<ValueType = string> = 
      { label: string, value: ValueType, icons?: React.ComponentType<any>[] }

Siden NormalizedDropdownItemType er en generisk type så kan value være hvilken som helst type. TypeScript vil da også gi deg riktig type ut i onChange. Den er satt til standard som string da dette er vanligste praksis.

Liste med valgalternaltiver

Listen med valgalternaltiver sendes inn gjennom items-prop-en. items har typen PotentiallyAsyncDropdownItems som vil si den støtter tre typer input: liste med DropdownItemType, synkrone funksjoner og asynkrone funksjoner – de to siste kan du lese mer om under Hente valgalternaltiver fra nettverkskall.

DropdownItemType er enten en string eller et objekt med label, value og valgfritt icons – se under.

// Definition of DropdownItemType
type DropdownItemType<ValueType = string> = 
      string |
      { label: string, value: ValueType, icons?: React.ComponentType<any>[] }

Disse kan også blandes slik at følgende også vil være et gyldig items-input:

// Valid mixed type items input
const dropdownItems = [
  "choice1",
  { label: "Second choice", value: "choice2" },
  { lable: "Third choice", value: "choice3", icons: [FunnyIcon1, FunnyIcon2] }
]

Søkbar dropdown

Dropdown-en er også tilgjenglig i en søkbar versjon kalt SearchableDropdown. Denne fungerer i utgangspunktet helt likt som Dropdown, men har i tillegg støtte for å filterer på de tilgjengelige valgmulighetene. Som standard er filtreringen bassert på en enkel regex som sjekker om input-et er en del av valgalternaltivet, ønsker du å endre denne kan du skrive din egen filtreringsfunksjon – se Egendefinert filtreringsfunksjon.

Se et eksempel på hvordan du bruker SearchableDropdown under Søkbar dropdown-eksempelet.

Egendefinert filtreringsfunksjon

Du kan gi inn din egen filtreringsfunksjon til SearchableDropdown gjennom prop-en itemFilter. Dette kan være nyttig hvis du f.eks ønsker å implementere fuzzy search eller ignorere noen tegn fra input-et når du filtrerer. itemFilter tar inn en funksjon med item (valgalternaltivet som skal sjekkes mot filtreringen) og inputValue (det bruker for øyeblikket har skrevet inn i inputfeltet) som input. Funksjonen skal returnere true eller false avhengig av om gjeldende item skal være med i listen over valg eller ikke.

Se eksempel på dette under Søkbar dropdown med egendefingert filtreringsfunksjon-eksempelet.

Hente valgalternaltiver fra nettverkskall

Hvis listen din med valg skal hentes fra et API eller lignende er det mulig å sende inn en memoisert funksjon til items i stedet for en liste med valg. Denne funksjonen kan enten være synkron eller asynkron og må enten returnere en liste med DropdownItemType direkte eller gjennom et Promise. OBS: du må huske å memoisere funksjonen ved å bruke React.useCallback, ellers vil den kjøre funksjonen din oftere enn nødvendig!

For søkbare dropdowns kan funksjonen i items også bruke inputValue-verdien som sendes inn å f.eks gjøre en query mot et API-et. I dette tilfellet kan du også bruke prop-en debounceTimeout til å bestemme hvor lenge det skal ventes før et nytt kall mot funksjonen skal kjøres etter brukeres slutter å skrive.

For å avbryte utdaterte kall og hindre 'state update of unmounted component' kan du bruke abortControllerRef som sendes inn som andre argument til funksjonen. abortControllerRef.current.signal inneholder et signal som sier fra når asynkrone kall bør avbrytes og er støttet ut av boksen i f.eks fetch og axios. Les mer om AbortController på Mozilla sine sider og se eksempel på alt i bruk under Dropdown med valg fra nettverkskall.

Innebygd nettleser-dropdown med styling (NativeDropdown)

Hvis du enten ønsker en veldig lettvektig dropdown eller en dropdown som bruker det innebygde grensesnittet til brukerens enhet kan du bruke NativeDropdown. Denne er style-et til å følge Entur sin merkevare, men når den trykkes på vil nettleseren sin egen dropdown åpnes i stedet. Denne varianten er mye simplere og vil, av sin natur, ikke se lik ut på tvers av enhetern når den åpnes. En slik løsning kan være praktisk i små, enkle løsninger eller, i noen tilfeller, mobil-grensesnitt.

NativeDropdown er i bunn en HTML-select-input – se MDN web docs for mer info – og fungerer for det meste likt som den. Det er dog noen forskjeller, de viktigste er som følger:

  • i stedet for å ha <option /> som children gir du inn liste med valg på samme måte som Dropdown og SearchableDropdown – se Liste med valgalternaltiver.
  • onChange er forskjellig fra den originale onchange og ser ut som følger:
    
      type onChange = (
        value: string;
        selectedItem: NormalizedDropdownItemType | null;
        target: EventTarget & HTMLSelectElement;
      ) => void;
    
  • i stedet for selectedItem brukes value, dette på samme måte som i HTML sin select-input

Se et eksempel på bruk av NativeDropdown under eksempelet Native dropdown

Universell utforming

Kommer info om dette snart

Retningslinjer

Kommer snart

Eksempler

Vanlig dropdown

Her finner du en vanlig, ikke-søkbar dropdown med standard-props.

() => {
const [selected, setSelected] = React.useState(null)
return (
<Dropdown
label="Velg by"
items={cities}
selectedItem={selected}
onChange={setSelected}
/>
)
}

Søkbar dropdown

Her finner du en vanlig, søkbar dropdown med standard-props.

() => {
const [selected, setSelected] = React.useState(null)
return (
<SearchableDropdown
label="Velg by"
items={cities}
selectedItem={selected}
onChange={setSelected}
/>
)
}

Søkbar dropdown med egendefinert filtreringsfunksjon

I dette eksempelet brukes en fuzzyMatch-implementasjon til å utføre en mer tilgivende filtrering av de tilgjengelige valgene.

() => {
const [selected, setSelected] = React.useState(null)
return (
<SearchableDropdown
label="Fuzzy search filter"
items={cities}
selectedItem={selected}
onChange={setSelected}
itemFilter={(item, inputValue) =>
fuzzyMatch(inputValue, item.label) > 0.5
}
/>
)
}

Hvis du øsker at brukeren kan fjerne valget sitt etter å ha gjort det kan du enten bruke prop-en clearable eller selv sende inn valgt verdien null til selectedItem-prop-en. clearable legger til en knapp i dropdownen som fjerner valgt element. Funksjonaliteten er lik for både vanlig og søkbar dropdown.

() => {
const [selected, setSelected] = React.useState(null)
return (
<>
<span>
<IconButton onClick={() => setSelected(null)}>
<ResetIcon />
Tilbakestill
</IconButton>
</span>
<Dropdown
label="Velg by"
items={cities}
selectedItem={selected}
onChange={setSelected}
clearable
labelClearSelectedItem="fjern valgt by"
/>
</>
)
}

Her har vi en eksempelfunksjon fetchItems som bruker abortControllerRef-argumentet og henter inn data fra et test-API. Denne funksjonen settes så inn i items-prop-en og vi får data fra det eksterne API-et listet opp når data-en er mottatt.

() => {
// Husk å bruke useCallback for å unngå at funksjonen kjøres oftere enn nødvendig
const fetchItems = React.useCallback(async (_, abortControllerRef) => {
try {
const response = await fetch(
`https://dummyjson.com/products/categories`,
// Bruk signalet fra abortController for å avbryte utdaterte kall
{ signal: abortControllerRef.current.signal },
)
const data = await response.json()
if (data.message !== undefined) return [data.message]
return data
} catch (error) {
// AbortError må sendes videre til komponenten for å håndtere cleanup riktig
if (error && error.name === 'AbortError') throw error
console.error('noe galt')
return []
}
}, [])
const [selected, setSelected] = React.useState(null)
return (
<Dropdown
label="Extenal API list"
items={fetchItems}
selectedItem={selected}
onChange={setSelected}
/>
)
}

Søkbar dropdown med valg fra nettverkskall bassert på tekstinput

Her har vi en eksempelfunksjon fetchItems som henter inn data fra et test-API. fetchItems tar inn nåværende inputValue og abortControllerRef og bruker det til å gjøre en query mot API-et. Denne funksjonen settes så inn i items-prop-en og vi får data fra det eksterne API-et listet opp med query bassert på det som skrives inn.

() => {
// Husk å bruke useCallback for å unngå at funksjonen kjøres oftere enn nødvendig
const fetchItems = React.useCallback(
async (inputValue, abortControllerRef) => {
try {
const response = await fetch(
`https://dummyjson.com/products/search?q=${inputValue}&limit=15&select=title`,
// Bruk signalet fra abortController for å avbryte utdaterte kall
{ signal: abortControllerRef.current.signal },
)
const data = await response.json()
if (data.message !== undefined) return [data.message]
const processedData = data.products.map(item => {
return { label: item.title, value: item.id }
})
return processedData
} catch (error) {
// AbortError må sendes videre til komponenten for å håndtere cleanup riktig
if (error && error.name === 'AbortError') throw error
console.error('noe galt')
return []
}
},
[],
)
const [selected, setSelected] = React.useState(null)
return (
<SearchableDropdown
label="Extenal API list"
items={fetchItems}
selectedItem={selected}
onChange={setSelected}
/>
)
}

Native dropdown

Her finner du en native dropdown med standard-props.

() => {
const [selected, setSelected] = React.useState(null)
return (
<NativeDropdown
label="Velg by"
items={cities}
value={selected}
onChange={({ value }) => setSelected(value)}
/>
)
}

Tilgjengelige props

import { Dropdown } from '@entur/dropdown';
NavnTypeDefault-verdiBeskrivelse
itemsPotentiallyAsyncDropdownItemType<ValueType>

Tilgjengelige valg i dropdown-en

selectedItemNormalizedDropdownItemType<ValueType> | null

Valgt verdi. Bruk null for ingen verdi.

onChange?((selectedItem: NormalizedDropdownItemType<ValueType> | null) => void | Dispatch<SetStateAction<NormalizedDropdownItemType<ValueType> | null>>)

Callback ved valg som skal oppdatere selectedItem

labelstring

Beskrivende tekst som forklarer feltet

placeholder?string

Placeholder-tekst når ingenting er satt

clearable?boolean false

Om man skal ha mulighet for å nullstille Dropdown-en

selectOnTab?boolean

Lar brukeren velge ved å “tab-e” seg ut av komponenten

selectOnBlur?boolean

@deprecated Bruk selectOnTab i stedet

Lar brukeren velge ved å “tab-e” seg ut av komponenten

disabled?boolean

Deaktiver dropdown-en

readOnly?boolean

Setter dropdown-en i read-only modus

variant?VariantType

Hvilken valideringsvariant som gjelder

feedback?string

Valideringsmelding, brukes sammen med variant

prepend?ReactNode

Tekst eller ikon som kommer før dropdown-en

loadingText?string 'Laster inn …'

En tekst som beskriver hva som skjer når man venter på items

labelClearSelectedItem?string "fjern valgt"

Om man skal ha mulighet for å nullstille Dropdown-en

disableLabelAnimation?boolean false

Plasserer labelen statisk på toppen av inputfeltet

className?string

Ekstra klassenavn

listStyle?{ [key: string]: any; }

Styling som sendes ned til Dropdown-lista

style?{ [key: string]: any; }

Styling for Dropdown-en

ariaLabelCloseList?string "Lukk liste med valg"

Tekst for skjemleser for knapp som lukker listen med valg

ariaLabelOpenList?string "Åpne liste med valg"

Tekst for skjemleser for knapp som åpner listen med valg

ariaLabelChosenSingular?string 'valgt'

Ord for at et element er valgt i entall eks. ‘Element 1, valgt

ariaLabelSelectedItem?string ', valgt element, trykk for å fjerne'

Tekst for skjermleser som beskriver statusen til et element som valgt

SearchableDropdown

import { SearchableDropdown } from '@entur/dropdown';
NavnTypeDefault-verdiBeskrivelse
itemsPotentiallyAsyncDropdownItemType<ValueType>

Tilgjengelige valg i dropdown-en

selectedItemNormalizedDropdownItemType<ValueType> | null

Valgt element. Bruk null for ingen verdi

onChange?((selectedItem: NormalizedDropdownItemType<ValueType> | null) => void | Dispatch<SetStateAction<NormalizedDropdownItemType<ValueType> | null>>)

Callback ved valg som skal brukes til å oppdatere selectedItem

itemFilter?((item: NormalizedDropdownItemType<ValueType>, inputValue: string ) => boolean) Regex-test som sjekker om item.label inneholder input-teksten

Filtreringen som brukes når man skriver inn tekst i inputfeltet

labelstring

Beskrivende tekst som forklarer feltet

placeholder?string

Placeholder-tekst når ingenting er satt

clearable?boolean true

Vis knapp for å nullstille Dropdown-en skal vises

disableLabelAnimation?boolean false

Plasserer labelen statisk på toppen av inputfeltet

debounceTimeout?number

Antall millisekunder man venter etter tekstinput før det gjøres kall for å oppdatere items Denne er kun relevant hvis du sender inn en funksjon som items.

disabled?boolean

Deaktiver dropdown-en

selectOnTab?boolean

Lar brukeren velge ved å “tab-e” seg ut av komponenten

selectOnBlur?boolean

@deprecated Bruk selectOnTab i stedet

Lar brukeren velge ved å “tab-e” seg ut av komponenten

noMatchesText?string "Ingen treff for søket"

Tekst som kommer opp når det ikke er noe treff på filtreringsøket

readOnly?boolean false

Gjør dropdown-en til å kun kunne leses

prepend?ReactNode

Tekst eller ikon som kommer før dropdown-en

loadingText?string

En tekst som beskriver hva som skjer når man venter på items

variant?VariantType

Hvilken valideringsvariant som gjelder

feedback?string

Valideringsmelding, brukes sammen med variant

className?string
style?{ [key: string]: any; }
listStyle?{ [key: string]: any; }

Style som kun påføres listeelementet

labelClearSelectedItem?string "fjern valgt"

Tekst som beskriver at man fjerner valget sitt

ariaLabelCloseList?string "Lukk liste med valg"

Tekst for skjemleser for knapp som lukker listen med valg

ariaLabelOpenList?string "Åpne liste med valg"

Tekst for skjemleser for knapp som åpner listen med valg

ariaLabelChosenSingular?string "valgt"

Ord for at et element er valgt i entall eks. ‘Element 1, valgt

ariaLabelSelectedItem?string ", valgt element, trykk for å fjerne"

Tekst for skjermleser som beskriver statusen til et element som valgt

NativeDropdown

import { NativeDropdown } from '@entur/dropdown';
NavnTypeDefault-verdiBeskrivelse
className?string

Ekstra klassenavn

disabled?boolean false

For å deaktivere dropdow-nen

feedback?string

Valideringsmelding, brukes sammen med variant

itemsPotentiallyAsyncDropdownItemType<ValueType>

Alle valg for dropdown-en å ha

labelstring

Beskrivende tekst som forklarer feltet

onChange?(({ value, selectedItem, target, }: { value: string; selectedItem: NormalizedDropdownItemType<ValueType> | null; target: EventTarget & HTMLSelectElement; }) => void)

En callback for endringer av value Obs: merk at parameter her denne ikke er samme som i en HTML select. Bruk { target } hvis du trenger info om select-elementet som ble trykket på

prepend?ReactNode

Tekst eller ikon som kommer før dropdown-en

readOnly?boolean false

Setter dropdown-en i read-only modus

selectedItem?NormalizedDropdownItemType<ValueType> | null

Den valgte verdien som NormalizedDropdownItemType (Brukes når komponenten er ‘controlled’)

value?string

Den valgte verdien som sting (Brukes når komponenten er ‘controlled)

variant?VariantType

Hvilken valideringsvariant som gjelder

disableLabelAnimation?boolean false

Plasserer labelen statisk på toppen av inputfeltet

Rediger denne siden på Bitbucket