Listbox
Faking a <select>
with <ul hidden role='listbox'>
Data source
nuances on what appears in the template blueprint if using Enum types as choices in a listbox:
django.db.models.IntegerChoices
{{form.field.value}}
is an integer{{field.value.label}}
is the human-readable text
django.db.models.TextChoices
{{field.value.label}}
will result inNone
{{field.value}}
is the human-readable text
It's possible to use get_FOO_display()
but with respect to this fake <select>
implementation, only the BoundField
is passed to the template fragment.
Required Blueprint
Javascript checks
document.querySelector(id) // (1)
// Hidden field + label (2)
document.querySelector(`#${id} > select[hidden]`)
document.querySelector(`#${id} label`)
// Button with text (3)
document.querySelector(`#${id} button`)
document.querySelector(`#${id} button > span`)
// Listbox options (4)
document.querySelector(`#${id} ul[hidden][role=listbox]`)
document.querySelectorAll(`#${id} ul[hidden][role=listbox] > li`)
- The container will contain component DOM nodes
- Should contain direct child
<select hidden>
and associated<label>
(need not be a direct child) - Child
<button>
with a direct child<span>
- Child
<ul hidden role='listbox'>
with direct children<li>
Sample + Implementation
- Common script to both menubar and listbox
- Specific script enabling
doSelect()
Selector Styling
When an <li>
on the listbox receives :focus
:
aria-selected='true'
appears on<li>
.aria-selected='false'
is set on the other<li>
aria-activedescendant
appears on<ul>
pointing to the auto-generated id of<li>
.
These can then be used as a selector to style the focused element.