Skip to main content

Combobox Review

ComboBox is used as an alternative to a select box, where many items must be chosen from, or to assist in finding values for text input.

The ComboBox offers a list of items to choose from and it also exposes the value of selected item(s) via its value property. Please note that this value is distinct from the contained Input's value. The two values can be synced with the force attribute.

Examples #

Open in new window
<duet-layout center>
<div slot="main">
<duet-card>
<duet-combobox id="duet-combobox">
<duet-input label="Combobox Postalcode example" icon="form-location" expand caption="use arrow keys to navigate, type to search list"></duet-input>
</duet-combobox>
</duet-card>
</div>
</duet-layout>


<script>
(function() {
var combobox = document.querySelectorAll("#duet-combobox")

// Zipcode map to place
combobox[0].items = [
{id:0, value: "49200", name: "Heinlahti"},
{id:1, value: "49210", name: "Huutjärvi"},
{id:2, value: "49220", name: "Siltakylä"},
{id:3, value: "49240", name: "Purola"},
{id:4, value: "49270", name: "Something"},
{id:5, value: "49290", name: "Vastila"}
]

combobox[0].addEventListener("duetChange", function (e) {
console.log("Combobox value changed:", e.detail)
})
})()

</script>
Open in new window
<duet-layout center>
<div slot="main">
<duet-card>
<duet-combobox
items='[{"id":"0", "value": "49200", "name": "Heinlahti"},{"id":"1", "value": "49210", "name": "Huutjärvi"}]'
>

<duet-input label="Anna postinumerosi" label-hidden icon="form-location"></duet-input>
</duet-combobox>
</duet-card>
</div>
</duet-layout>
Open in new window
<duet-layout center>
<div slot="main">
<duet-card>
<duet-combobox id="duet-combobox-custom-formatter" force>
<duet-input label="Combobox Postalcode with custom formatter & tags" placeholder="select a postal code" icon="form-location" expand caption="use arrow keys to navigate, type to search list"></duet-input>
</duet-combobox>

</duet-card>
</div>
</duet-layout>


<script>
(function(){
var combobox = document.querySelectorAll("#duet-combobox-custom-formatter")
// Zipcode map to place
combobox[0].items = [
{id:0, value: "49200", name: "Heinlahti", tags: ["something else", "Heinlahti"]},
{id:1, value: "49210", name: "Huutjärvi", tags: ["49200", "Heinlahti"]},
{id:2, value: "49220", name: "Siltakylä", tags: ["49200", "Heinlahti"]},
{id:3, value: "49240", name: "Purola", tags: ["49200", "Heinlahti"]},
{id:4, value: "49270", name: "Something", tags: ["49200", "Heinlahti"]},
{id:5, value: "49290", name: "Vastila", tags: ["49200", "Heinlahti"]}
]

combobox[0].formatter = (item ) => {
return item.value + "" + item.name
}

combobox[0].addEventListener("duetChange", function (e) {
console.log("Combobox value changed:", e.detail)
})
})()
</script>
Open in new window
<duet-layout center>
<div slot="main">
<duet-card>
<duet-combobox id="duet-combobox-custom-formatter-with-errorchecking" force>
<duet-input label="Combobox Postalcode with custom formatter & tags" placeholder="select a postal code" icon="form-location" expand caption="this will error out if value selected is not the first with id:49200"></duet-input>
</duet-combobox>

</duet-card>
</div>
</duet-layout>


<script>
(function(){
var combobox = document.querySelectorAll("#duet-combobox-custom-formatter-with-errorchecking")
var input = document.querySelectorAll("duet-input")
// Zipcode map to place
combobox[0].items = [
{id:0, value: "49200", name: "Heinlahti", tags: ["something else", "Heinlahti"]},
{id:1, value: "49210", name: "Huutjärvi", tags: ["49200", "Heinlahti"]},
{id:2, value: "49220", name: "Siltakylä", tags: ["49200", "Heinlahti"]},
{id:3, value: "49240", name: "Purola", tags: ["49200", "Heinlahti"]},
{id:4, value: "49270", name: "Something", tags: ["49200", "Heinlahti"]},
{id:5, value: "49290", name: "Vastila", tags: ["49200", "Heinlahti"]}
]

combobox[0].formatter = (item ) => {
return item.value + " ⊨ " + item.name
}

combobox[0].addEventListener("duetChange", function (e) {
if(e.detail.value !== "49200") {
input[0].error = "Only postalcode with id:49200 is allowed as selection"
}else {
input[0].error = undefined
}
console.log("Combobox value changed:", e.detail)
})
}())
</script>
Open in new window
<duet-layout center>
<div slot="main">
<duet-card>
<duet-combobox min-characters="3" id="duet-combobox-with-min-characters" >
<duet-input label="Combobox Postalcode example" icon="form-location" expand caption="use arrow keys to navigate, type to search list"></duet-input>
</duet-combobox>

</duet-card>
</div>
</duet-layout>


<script>
(function(){
var combobox = document.querySelectorAll("#duet-combobox-with-min-characters")
// Zipcode map to place
combobox[0].items = [
{id:0, value: "49200", name: "Heinlahti"},
{id:1, value: "49210", name: "Huutjärvi"},
{id:2, value: "49220", name: "Siltakylä"},
{id:3, value: "49240", name: "Purola"},
{id:4, value: "49270", name: "Something"},
{id:5, value: "49290", name: "Vastila"}
]

combobox[0].addEventListener("duetChange", function (e) {
console.log("Combobox value changed:", e.detail)
})
}())
</script>
Open in new window
<duet-layout center>
<div slot="main">
<duet-card>
<duet-combobox open-list-on-click id="duet-combobox-open-on-click">
<duet-input label="Combobox Postalcode example" icon="form-location" expand caption="use arrow keys to navigate, type to search list"></duet-input>
</duet-combobox>

</duet-card>
</div>
</duet-layout>


<script>
(function(){
var combobox = document.querySelectorAll("#duet-combobox-open-on-click")
// Zipcode map to place
combobox[0].items = [
{id:0, value: "49200", name: "Heinlahti"},
{id:1, value: "49210", name: "Huutjärvi"},
{id:2, value: "49220", name: "Siltakylä"},
{id:3, value: "49240", name: "Purola"},
{id:4, value: "49270", name: "Something"},
{id:5, value: "49290", name: "Vastila"}
]

combobox[0].addEventListener("duetChange", function (e) {
console.log("Combobox value changed:", e.detail)
})
}())

</script>
Open in new window
<duet-layout center>
<div slot="main">
<duet-card>
<duet-combobox value="49240" id="duet-combobox-preselected-value">
<duet-input label="Combobox Postalcode example" icon="form-location" expand caption="use arrow keys to navigate, type to search list"></duet-input>
</duet-combobox>
</duet-card>
</div>
</duet-layout>


<script>
(function(){
var combobox = document.querySelectorAll("#duet-combobox-preselected-value")
// Zipcode map to place
combobox[0].items = [
{id:0, value: "49200", name: "Heinlahti"},
{id:1, value: "49210", name: "Huutjärvi"},
{id:2, value: "49220", name: "Siltakylä"},
{id:3, value: "49240", name: "Purola"},
{id:4, value: "49270", name: "Something"},
{id:5, value: "49290", name: "Vastila"}
]

combobox[0].addEventListener("duetChange", function (e) {
console.log("Combobox value changed:", e.detail)
})
}())

</script>
Open in new window
<duet-layout center>
<div slot="main">
<duet-card>
<!--
Combobox will generate the text input if you don't include it. In this case you need to add the label and
optional capition to the combobox component.
-->

<duet-combobox
filter-type="includes"
label="Choose disease"
caption="use arrow keys to navigate, type to search list"
multiple
open-list-on-click
>
</duet-combobox>
</duet-card>
</div>
</duet-layout>


<script>
(function() {
var combobox = document.querySelector("duet-combobox")
var items = [
{ "value":"B33.3", "name":"Muut retrovirusinfektiot", "id":"1" },
{ "value":"B33.8", "name":"Muu määritetty virussairaus", "id":"1" }, // for duplicate id' you will get a warning
{ "value":"B34", "name":"Virussair.sijainti ei määrit" }, // if no id is provided, it will be generated
{ "value":"B34.0", "name":"Määrittämätön adenovirusinfekt", "id":"3" },
{ "value":"B34.1", "name":"Määrittämätön enterovirusinfek", "id":"4" },
{ "value":"B34.2", "name":"Määrittämätön koronavirusinfek", "id":"5" },
{ "value":"B34.3", "name":"Määrittämätön parvovirusinfekt", "id":"6" },
{ "value":"B34.4", "name":"Määrittämätön papovavirusinfek", "id":"7" },
{ "value":"B34.8", "name":"Muu virusinf. sijainti ei määr", "id":"8" },
{ "value":"B34.9", "name":"Määrittämätön virusinfektio", "id":"9" },
{ "value":"B35-B49", "name":"Sienitaudit", "id":"10" },
{ "value":"B35", "name":"Ihon silsasairaus", "id":"11" },
{ "value":"B35.0", "name":"Pälvisilsa ja/tai partasilsa", "id":"12" },
{ "value":"B35.1", "name":"Kynsisilsa", "id":"13" },
{ "value":"B35.2", "name":"Käsisilsa", "id":"14" },
{ "value":"B35.3", "name":"Jalkasilsa", "id":"15" },
{ "value":"B35.4", "name":"Vartalosilsa", "id":"16" },
{ "value":"B35.5", "name":"Tinea imbricata", "id":"17" },
{ "value":"B35.6", "name":"Nivustaipeen silsa", "id":"18" },
{ "value":"B35.8", "name":"Muu ihon silsasairaus", "id":"19" },
{ "value":"B35.9", "name":"Määrittämätön ihon silsasair", "id":"20" },
{ "value":"B36", "name":"Muut pinnalliset sienitaudit", "id":"21" },
{ "value":"B36.0", "name":"Savipuoli", "id":"22" },
{ "value":"B36.1", "name":"Mustasilsa", "id":"23" },
{ "value":"B36.2", "name":"Valkosilsa", "id":"24" }
]
combobox.items = items
combobox.addEventListener("duetChange", function (e) {
console.log("Combobox value changed:", e.detail)
})
})()

</script>

Properties #

Property Attribute Description Type Default
accessibleLabelDefaults accessible-label-defaults Defaults for the accessible labels for the select items DuetLangObject | string { en: { heading: "Select:", item: "{name}, ({current} of {total})", itemFiltered: "{name}, ({current} of {total}, {hiddenItems} filtered)", }, fi: { heading: "Valitse:", item: "{name}, ({current}/{total})", itemFiltered: "{name}, ({current}/{total}, {hiddenItems} suodatettu)", }, sv: { heading: "Välj:", item: "{name}, ({current} av {total})", itemFiltered: "{name}, ({current} av {total}, {hiddenItems} filtrerade)", }, }
accessibleLabels -- Accessible labels for the select items { [x: string]: string; } getLocaleString( this.accessibleLabelDefaults, getLanguage() )
caption caption Caption for the input if input is not provided as a slotted element. string ""
filterType filter-type Defines if filtering of items should be done by includes or startsWith "includes" | "startsWith" "startsWith"
force force Force the user to make a selection (typing things in the input field will only be used for list search). This property also sync input value with selected value on blur. boolean false
formatter -- A hook to overwrite how the values are displayed in the input field after a User select an item (item: DuetComboboxItem) => string (item: DuetComboboxItem) => item && item.name ? item.name : ""
items items Array of item objects. Each item should have properties name, value and optionally id. If id is not provided, it will be generated. Alternatively, an array of strings can be provided, in which case the strings will be used for name, value and id. any undefined
label label Label for the input if input is not provided as a slotted element. string ""
minCharacters min-characters Defines minimum number of characters that must be given to show search results number 1
multiple multiple Allow multiple selections. Selections are displayed as DuetChips. boolean false
openListOnClick open-list-on-click Defines if items list should always open after clicking on input boolean false
theme theme Theme of the combobox. "" | "default" | "turva" ""
value value Value of selected item/s. If multiple is true, value is an array of selected items, else it's a string. string | string[] undefined

Events #

Event Description Type
duetChange Emitted when selected item changed. CustomEvent<{ originalEvent?: Event; component: "duet-combobox"; value: any; item: DuetComboboxItem; }>

Methods #

formatItem(item: DuetComboboxItem) => Promise<string> #

Exposes a formatter function to format the item value displayed after a user selects an item

Parameters #

Name Type Description
item { id?: string; value: any; name: string; html?: string; tags?: string[]; } : DuetComboboxItem

Returns #

Type: Promise<string>


Usage #

This section includes guidelines for designers and developers about the usage of this component in different contexts.

Normal usage with javascript #

Don't use the standard .value attribute to do any validation on, you should use the duetChange event instead - it provides better data for filtering

When to use #

  • As a more userfirendly alternative to a standard select box, however it should only be used when the number of items are unwieldy.

When not to use #

  • For small list of items
  • For items that have groupings

Accessibility #

This component has been validated to meet the WCAG 2.1 AA accessibility guidelines. You can find additional information regarding accessibility of this component below.


Integration

For integration, event and theming guidelines, please see Using Components. This documentation explains how to implement and use Duet’s components across different technologies like Angular, React or Vanilla JavaScript.

Integration guidelines


Tutorials

Follow these practical tutorials to learn how to build simple page layouts using Duet’s CSS Framework, Web Components and other features:

Tutorials

Building Layouts

Tutorials

Using CLI Tools

Tutorials

Creating Custom Patterns

Tutorials

Server Side Rendering

Tutorials

Sharing Prototypes

Tutorials

Usage With Markdown


Troubleshooting

If you experience any issues while using a component, please head over to the Support page for more guidelines and help.