material-autocomplete

Editable combobox over the select anatomy — client-side filtering of slotted <material-option>s, remote src endpoint (debounced, select2-compatible JSON), single or multiple chips. Strict: only option values commit.

single, static options — typing filters client-side with match highlight; ↑/↓ + Enter commit, Esc/blur revert free text; the selected option shows a check

Acme Corp Globex Ltd Initech Hooli Stark Industries Wayne Enterprises Tyrell Corp Aperture Science Cyberdyne Systems Massive Dynamic

value:

filled variant, leading icon, supporting text, disabled option

Grace Hopper Ada Lovelace Dieter Rams Alan Turing Barbara Liskov

multiple — chips + checkbox rows, menu stays open on toggle, Backspace with empty input removes the last chip; posts one form entry per value

Bug Feature Documentation Performance Accessibility Internationalization Security

values: ["bug"]

remote src — the server filters (?q=…, debounced 250ms, stale requests aborted); JSON is [{value,label}], {results:[…]} or select2-style {id,text}. This demo mocks /demo-api/countries with 400ms latency.

remote + multiple + min-chars="2" — prompts until 2 characters are typed; selections made from earlier result pages keep their labels via the value→label cache

Japan

form integration — form-associated (Django request.POST.getlist('countries')), required validation, reset restores initial selection

Acme Corp Globex Ltd Initech

posted:

RTL — label, chips, chevron and listbox mirror with the reading direction

الرياض جدة دبي القاهرة عمّان

error + disabled states

EMEA APAC EMEA
Sample usage (Django)
<!-- static: options in the template, filtered client-side -->
<material-autocomplete name="vendor" label="Vendor" required>
  {% for v in vendors %}
  <material-option value="{{ v.pk }}" {% if v == form.vendor.value %}selected{% endif %}>
    {{ v.name }}
  </material-option>
  {% endfor %}
</material-autocomplete>

<!-- remote: a JSON view filters; render the current selection so the
     label is known before the first fetch -->
<material-autocomplete name="assignee" label="Assignee"
                       src="{% url 'user-autocomplete' %}" min-chars="2">
  {% if form.instance.assignee %}
  <material-option value="{{ form.instance.assignee_id }}" selected>
    {{ form.instance.assignee }}
  </material-option>
  {% endif %}
</material-autocomplete>

# the view — any of these shapes works, including select2's:
def user_autocomplete(request):
    q = request.GET.get("q", "")
    users = User.objects.filter(username__icontains=q)[:20]
    return JsonResponse([{"value": u.pk, "label": u.username} for u in users], safe=False)

<script>
  el.addEventListener('valueChange', (e) => e.detail);     // {value, values}
  el.addEventListener('materialSearch', (e) => e.detail);  // {query} — event-driven mode
</script>