ComboBox

Edit on Github
Open in Playground View Demo

Introduction

This sample demonstrastes a classic dropdown combo, with a text field which filters the dropdown elements according to the user's input. The options are rendered via amp-list.

<!doctype html>
<html ⚡>
<head>
  <title>ComboBox</title>
  <meta charset="utf-8">
  <link rel="canonical" href="https://ampbyexample.com/30_advanced/combobox/">

  <meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1">
  <script async src="https://cdn.ampproject.org/v0.js"></script>

Setup

The amp-selector component is used for the user to select amongst the dropdown list options.

<script async custom-element="amp-selector" src="https://cdn.ampproject.org/v0/amp-selector-0.1.js"></script>

The amp-bind component is used for the filtering of the dropdown options according to the user's input.

<script async custom-element="amp-bind" src="https://cdn.ampproject.org/v0/amp-bind-0.1.js"></script>

The amp-list component is used to generate the dropdown list options.

<script async custom-element="amp-list" src="https://cdn.ampproject.org/v0/amp-list-0.1.js"></script>

The amp-mustache is used to generate the dropdown list options' template.

<script async custom-template="amp-mustache" src="https://cdn.ampproject.org/v0/amp-mustache-0.1.js"></script>

Basic Usage

This example includes two inputs. One is the input in which the user writes the text and the other is a hidden input, where the id value of the selected option is stored and could be submitted in a form.

The option attribute of the amp-selector's options, contain the id of the element, as well as its title, seperated by a comma. This is done so that both values can be accessed using the 'event.targetOption' property.

Example

<div class="dropdown-wrap">
  <label for="products-dropdown">Select your favorite food or beverage. Start typing to filter the results.</label>
  <div class="product-search select-wrap full-width">
    <div class="search-container">
      <input name="products-dropdown"
        type="hidden"
        [value]="foodId">
      <input id="query"
        name="query"
        autocomplete="off"
        placeholder="Select a product"
        type="text"
        class="search-box"
        on="input-debounced:AMP.setState({ query: event.value, inputText: event.value, autosuggest: event.value, comboExpanded: true}), autosuggest-list.show"
        [value]="inputText || ''"
        value="">

      <button on="tap:autosuggest-list.toggleVisibility, AMP.setState({ comboExpanded: !comboExpanded })"
        class="search-submit"
        type="button">
        <i [class]="comboExpanded ? 'arrow-up' : 'arrow-down'"
          class="arrow-down"></i>
      </button>
    </div>
    <amp-list class="autosuggest-box"
      single-item
      items="."
      layout="fixed-height"
      height="350"
      src="/json/food-options.json"
      id="autosuggest-list"
      hidden>
      <template type="amp-mustache">
        <amp-selector class="dropdown-selector"
          keyboard-select-mode="focus"
          layout="container"
          on="select:AMP.setState({
                                          query: '',
                                          inputText: event.targetOption.split(',')[1],
                                          foodId: event.targetOption.split(',')[0],
                                          comboExpanded: false
                                      }),
                                      autosuggest-list.hide">
          {{#items}}
          <div class="select-option no-outline {{Level}}"
            [class]="'select-option no-outline {{Level}} ' + (query == null || '{{LowerCaseTitle}}'.indexOf(query.toLowerCase()) >= 0 || '{{ParentCategoryTitle}}'.indexOf(query.toLowerCase()) >= 0 ? '' : 'hidden')"
            role="option"
            tabindex="0"
            on="tap:autosuggest-list.hide"
            option="{{Code}},{{Title}}">{{Title}}</div>
          {{/items}}
        </amp-selector>
      </template>
    </amp-list>

  </div>
</div>