Combobox
Things left to do:
- - Sorting (Hard because of streamed / injected elements, so we never fully know when we’re done)
- - Virtualization (Most likely in a separate component)
- - Tag only UI like TomSelect, instead of the current multiple editable UI, create a UI like Tom Select where you “inject” a placeholder option that can be selected.
- - Inline autocomplete support for non-input elements
Single Select Editable Combobox Examples
Editable Combobox without autocomplete
A combobox with autocomplete="off"
is editable, but will not guide the user along the popup list
of options and will not prefill the input.
URL Encoded:
Form Data:
List Autocomplete Combobox
“list” autocomplete will show the list and guide the user to the item in the list based on the string provided in the input.
URL Encoded:
Form Data:
Inline Autocomplete Combobox
Inline autocomplete will prefill the closest match for the user.
URL Encoded:
Form Data:
Autocomplete List & Inline Combobox (both)
A list + inline (“both”) combobox will both highlight the value in the input and select the item in the combobox list.
URL Encoded:
Form Data:
Filtering Results
When using autocomplete, you may want to filter results that don’t match and only show matching results.
URL Encoded:
Form Data:
Disabling options
Options can be disabled by passing the disabled
attribute to the <role-option>
element.
URL Encoded:
Form Data:
Multiple select comboboxes
Multiple combobox with value-type="formdata" and autocomplete="both"
URL Encoded:
Form Data:
Multiple combobox with autocomplete="both"
URL Encoded:
Form Data:
Multiple combobox with filtered results
URL Encoded:
Form Data:
Editable Multi select combobox with autocomplete “off”
URL Encoded:
Form Data:
Editable Multi select combobox with filtering
URL Encoded:
Form Data:
Using a “manual” selection type + allow-custom-values for multi-select.
TODO: Fix flickering with “Add option:” and hide it when no value.
URL Encoded:
Form Data:
Using a “manual” selection type for multiple selection with filtering
There are 2 types of multiple-selection-type
s. automatic
, which is the default, and manual
, which requires manually
selecting the option and will not automatically add it to the list of selected options.
URL Encoded:
Form Data:
API Reference
Imports
<!-- Auto registers as <role-combobox> -->
<script type="module" src="https://cdn.jsdelivr.net/npm/role-components/exports/combobox/combobox-register.js"></script>
<script type="module">
// Auto registers as <role-combobox>
import "https://cdn.jsdelivr.net/npm/role-components/exports/combobox/combobox-register.js"
// Manual Register
import RoleCombobox from "https://cdn.jsdelivr.net/npm/role-components/exports/combobox/combobox.js"
RoleCombobox.define()
// => Registers as <role-combobox>
</script>
// Auto registers as <role-combobox>
import "role-components/exports/combobox/combobox-register.js"
// Manual Register
import RoleCombobox "role-components/exports/combobox/combobox.js"
RoleCombobox.define()
// => Registers as <role-combobox>
Attributes
Name | Description | Reflects | Type | Default |
---|---|---|---|---|
[Attribute + Property]
editable
|
If true, the |
|
boolean
|
true
|
[Attribute + Property]
placement
|
The preferred placement of the popover. Note that the actual placement will vary as configured to keep the panel inside of the viewport. |
|
'top'
| 'top-start'
| 'top-end'
| 'bottom'
| 'bottom-start'
| 'bottom-end'
| 'right'
| 'right-start'
| 'right-end'
| 'left'
| 'left-start'
| 'left-end'
|
"bottom"
|
[Attribute]
current-placement
[Property] currentPlacement
|
The |
|
this["placement"] | null
|
-
|
[Attribute + Property]
strategy
|
Determines how the popover is positioned. Because you native “popover” API uses a fixed strategy, we use it as the default. |
|
Strategy
|
-
|
[Attribute + Property]
distance
|
The distance in pixels from which to offset along the “main axis”. Usually its equivalent to offsetY |
|
number
|
6
|
[Attribute + Property]
skidding
|
The distance in pixels from which to offset along the “cross axis”. Usually its equivalent to offsetX. |
|
number
|
-
|
[Attribute + Property]
arrow
|
Attaches an arrow to the popover. The arrow’s size and color can be customized using the |
|
boolean
|
-
|
[Attribute]
arrow-placement
[Property] arrowPlacement
|
The placement of the arrow. The default is |
|
'start' | 'end' | 'center' | 'anchor'
|
-
|
[Attribute]
arrow-padding
[Property] arrowPadding
|
The amount of padding between the arrow and the edges of the popover. If the popover has a border-radius, for example, this will prevent it from overflowing the corners. |
|
number
|
-
|
[Attribute + Property]
flip
|
When set, placement of the popover will flip to the opposite site to keep it in view. You can use
|
|
boolean
|
-
|
[Attribute]
flip-fallback-placements
[Property] flipFallbackPlacements
|
If the preferred placement doesn’t fit, popover will be tested in these fallback placements until one fits. Must be a string of any number of placements separated by a space, e.g. “top bottom left”. If no placement fits, the flip fallback strategy will be used instead. |
|
string
|
-
|
[Attribute]
flip-fallback-strategy
[Property] flipFallbackStrategy
|
When neither the preferred placement nor the fallback placements fit, this value will be used to determine whether the popover should be positioned using the best available fit based on available space or as it was initially preferred. |
|
'best-fit' | 'initial'
|
-
|
[Attribute]
flip-padding
[Property] flipPadding
|
The amount of padding, in pixels, to exceed before the flip behavior will occur. |
|
number
|
-
|
[Attribute + Property]
shift
|
Moves the popover along the axis to keep it in view when clipped. |
|
boolean
|
-
|
[Attribute]
shift-padding
[Property] shiftPadding
|
The amount of padding, in pixels, to exceed before the shift behavior will occur. |
|
number
|
-
|
[Attribute]
auto-size
[Property] autoSize
|
When set, this will cause the popover to automatically resize itself to prevent it from overflowing. |
|
null | 'horizontal' | 'vertical' | 'both'
|
-
|
[Attribute + Property]
sync
|
Syncs the popover’s width or height to that of the anchor element. |
|
null | 'width' | 'height' | 'both'
|
-
|
[Attribute]
auto-size-padding
[Property] autoSizePadding
|
The amount of padding, in pixels, to exceed before the auto-size behavior will occur. |
|
number
|
-
|
[Attribute]
hover-bridge
[Property] hoverBridge
|
When a gap exists between the anchor and the popover element, this option will add a “hover bridge” that fills the
gap using an invisible element. This makes listening for events such as |
|
boolean
|
-
|
[Attribute + Property]
expanded
|
-
|
|
boolean
|
false
|
[Attribute + Property]
multiple
|
Whether to allow multiple selections. |
|
boolean
|
false
|
[Attribute]
wrap-selection
[Property] wrapSelection
|
-
|
|
boolean
|
false
|
[Attribute + Property]
autocomplete
|
Any autocompletes of type |
|
'' | "off" | "inline" | "list" | "both"
|
''
|
[Attribute]
multiple-selection-type
[Property] multipleSelectionType
|
If set to “automatic” (default), it will be one single text input with delimited values. If set to “manual”, you will only enter 1 option at a time, and then need to confirm selection, and then the input will clear, and then you will add another selection. |
|
"automatic" | "manual"
|
"automatic"
|
[Attribute]
allow-custom-values
[Property] allowCustomValues
|
When |
|
boolean
|
false
|
[Attribute]
show-empty-results
[Property] showEmptyResults
|
If true, or |
|
boolean
|
false
|
[Attribute + Property]
delimiter
|
Used for multiple select comboboxes that use |
|
string
|
','
|
[Attribute + Property]
spacer
|
Used for multiple select comboboxes that use |
|
string
|
" "
|
[Attribute]
filter-results
[Property] filterResults
|
Whether or not to filter results based on what is typed into the combobox. |
|
boolean
|
false
|
[Attribute]
search-buffer-delay
[Property] searchBufferDelay
|
Delay before the search buffer returns to an empty string |
|
number
|
600
|
[Attribute]
value-type
[Property] valueType
|
Used for multiple selects. You can either have a string, or submit as multiple parameters in FormData
like a native |
|
"formdata" | "string"
|
"string"
|
[Attribute]
value
[Property] defaultValue
|
-
|
|
-
|
-
|
Events
Name | Description |
---|---|
change
|
-
|
input
|
-
|
Functions
Name | Description | Parameters |
---|---|---|
focus()
|
-
|
args
|
handleInput()
|
-
|
event: InputEvent
|
splitValue()
|
-
|
value: string
|
handleMultipleEditableInput()
|
-
|
event: InputEvent, triggerElement: HTMLButtonElement | HTMLInputElement
|
__shouldSelectSuggestedOption()
|
-
|
finalString: string, event: InputEvent
|
__findSuggestedOption()
|
-
|
finalString: string, event: InputEvent, newSelectedOptions: typeof this.selectedOptions
|
__handleConfirmInput()
|
-
|
event: InputEvent, triggerElement: HTMLButtonElement | HTMLInputElement
|
__handleAutomaticInput()
|
-
|
event: InputEvent, triggerElement: HTMLButtonElement | HTMLInputElement
|
handleSingleEditableInput()
|
-
|
event: InputEvent, triggerElement: typeof this.triggerElement
|
optionElementToOptionObject()
|
-
|
el: RoleOption
|
handleOptionFocus()
|
-
|
event: {target: null | RoleOption}
|
handleInputClick()
|
-
|
e: Event
|
handleOutsideClick()
|
-
|
e: Event
|
assignRandomId()
|
Users dont always provide ids on elements, and we need to make sure the id isn’t already taken. |
el: HTMLElement, id
|
updateListboxElement()
|
Adds proper attributes to the slotted listbox element |
-
|
handleInputFocus()
|
-
|
e: Event
|
updateTriggerElement()
|
Adds proper attributes to the slotted input element |
-
|
renderSelectedOptions()
|
-
|
-
|
formResetCallback()
|
-
|
-
|
setCurrent()
|
-
|
option: OptionObject
|
removeCurrent()
|
-
|
option: OptionObject
|
findOptionElement()
|
-
|
option: OptionObject
|
handleOptionClick()
|
-
|
evt: PointerEvent
|
handleOptionHover()
|
-
|
evt: Event
|
handleKeyUp()
|
Reset range when shiftKey goes up |
evt: KeyboardEvent
|
handleKeyDown()
|
-
|
evt: KeyboardEvent
|
selectFromClosestSelectedToCurrent()
|
Finds the closest selected option prior to the current option |
-
|
selectFromRangeStartToCurrent()
|
-
|
-
|
selectRange()
|
Selects all options in a range and deselects all options not in the range |
{ from, to }, options: Range
|
selectFromStartToCurrent()
|
-
|
startIndex: number
|
selectFromCurrentToEnd()
|
-
|
endIndex: number
|
escapeRegexChars()
|
Escape characters for regex matching. |
str: string
|
stringToRegex()
|
-
|
str: string
|
focusElementFromSearchBuffer()
|
-
|
-
|
select()
|
-
|
option: OptionObject
|
deselect()
|
-
|
option: OptionObject
|
selectAll()
|
Mark every element with [aria-selected=”true”] |
-
|
deselectAll()
|
Mark every element with [aria-selected=”false”] |
updateOptions
|
toggleSelected()
|
-
|
option: OptionObject
|
focusCurrent()
|
-
|
-
|
focusAt()
|
-
|
index: number
|
focusNext()
|
-
|
-
|
focusPrevious()
|
-
|
-
|
focusFirst()
|
-
|
-
|
focusLast()
|
-
|
-
|
scrollOptionIntoView()
|
-
|
selectedOption: OptionObject
|
scrollOptionElementIntoView()
|
-
|
optionElement: HTMLElement
|
isSelected()
|
-
|
option: OptionObject
|
updateOptions()
|
-
|
-
|
updateMultipleValue()
|
Updates formData / combobox.value |
force: boolean
|
updateCustomOption()
|
-
|
-
|
updateTriggerElementTextContentAndValue()
|
-
|
str: string
|
debounce()
|
-
|
callback: (...args: any[]) => any, options: { key: any, wait: number }
|