Combobox Review
ComboBox is used as an alternative to a select box, where many items must be chosen from
Examples #
<duet-layout center>
<div slot="main">
<duet-card>
<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>
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>
<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>
<duet-layout center>
<div slot="main">
<duet-card>
<duet-combobox 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>
var combobox = document.querySelectorAll("duet-combobox")
// 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>
<duet-layout center>
<div slot="main">
<duet-card>
<duet-combobox 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>
var combobox = document.querySelectorAll("duet-combobox")
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>
<duet-layout center>
<div slot="main">
<duet-card>
<duet-combobox min-characters="3" >
<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>
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>
<duet-layout center>
<div slot="main">
<duet-card>
<duet-combobox open-list-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>
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>
<duet-layout center>
<div slot="main">
<duet-card>
<duet-combobox value="49240">
<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>
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>
Properties #
Property | Attribute | Description | Type | Default |
---|---|---|---|---|
accessibleLabelDefaults | accessible-label-defaults | Placeholder defaults | 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 | -- | Hint text to display before the user types into the date picker input. | { [x: string]: string; } | getLocaleString( this.accessibleLabelDefaults, getLanguage() ) |
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) | 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. | any | undefined |
minCharacters | min-characters | Defines minimum number of characters that must be given to show search results | number | 1 |
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 | 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
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.
- You can use all the features of duet-input as normal
- Accessibility is provided via a dynamic select of chosen items via aria-selected
- The select text is hidden from screen readers and a label is read aloud instead, which informs the user of which item he/she selected out of how many items in the list
- it has been implemented to support https://www.levelaccess.com/differences-aria-1-0-1-1-changes-rolecombobox/
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.
Tutorials
Follow these practical tutorials to learn how to build simple page layouts using Duet’s CSS Framework, Web Components and other features:
Building Layouts
TutorialsUsing CLI Tools
TutorialsCreating Custom Patterns
TutorialsServer Side Rendering
TutorialsSharing Prototypes
TutorialsUsage With Markdown
Troubleshooting
If you experience any issues while using a component, please head over to the Support page for more guidelines and help.