AMP Roadshow is coming to Atlanta and Berlin!
AMP
  • websites

Simple Autosuggest

Introduction

This sample showcases how to implement an interactive autosuggest form field. The example below suggests cities in an address form, but the list of suggestions may contain any content, such as anticipated search queries, or product listings with images. You can see the full demo here. For a more complex example implementing an address input form with autosuggestion, take a look at this sample.

Next we include amp-selector to easily display results in an accessible list.

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

Then we include amp-list to request and display the autosuggest results.

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

Then we include amp-mustache to render the mustache templates inside the <amp-list>.

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

Finally we include amp-bind to track and update the page's state after user interactions.

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

Styles

Only a few CSS rules are necessary to implement the autosuggest overlay.

<style amp-custom>
  /* --------------------------------
     Necessary styles for the example
     -------------------------------- */
  :root {
    --color-bg-light: #FAFAFC;
    --autosuggest-width: 300px;
    --space-1: .5rem;  /* 8px */
    --space-2: 1rem;  /* 8px */
    --box-shadow-1: 0 1px 1px 0 rgba(0,0,0,.14), 0 1px 1px -1px rgba(0,0,0,.14), 0 1px 5px 0 rgba(0,0,0,.12);
  }
  #auto-suggest {
    position: absolute;
    width: var(--autosuggest-width);
    overflow-x: hidden;
    z-index: 100;
    box-shadow: var(--box-shadow-1);
    background-color: var(--color-bg-light);
  }
  #auto-suggest [option] {
    padding: var(--space-1);
  }

  /* ---------------------------------
     Additional non-autosuggest styles
     --------------------------------- */
  .preview-container {
    min-width: 320px;
    padding: var(--space-2);
  }
</style>

Data source

First we need to add a data source. Here we're using an inline amp-state declaration defining a list of cities in the US.

For long lists of suggestions, it's possible to fetch amp-state from a remote JSON endpoint using the src attribute.

<amp-state id="cities">
  <script type="application/json">
    [
      "Albany, New York",
      "Annapolis, Maryland",
      "Atlanta, Georgia",
      "Augusta, Maine",
      "Austin, Texas",
      "Baton Rouge, Louisiana",
      "Bismarck, North Dakota",
      "Boise, Idaho",
      "Boston, Massachusetts",
      "Carson City, Nevada",
      "Charleston, West Virginia",
      "Cheyenne, Wyoming",
      "Columbia, South Carolina",
      "Columbus, Ohio",
      "Concord, New Hampshire",
      "Denver, Colorado",
      "Des Moines, Iowa",
      "Dover, Delaware",
      "Frankfort, Kentucky",
      "Harrisburg, Pennsylvania",
      "Hartford, Connecticut",
      "Helena, Montana",
      "Honolulu, Hawaii",
      "Indianapolis, Indiana",
      "Jackson, Mississippi",
      "Jefferson City, Missouri",
      "Juneau, Alaska",
      "Lansing, Michigan",
      "Lincoln, Nebraska",
      "Little Rock, Arkansas",
      "Madison, Wisconsin",
      "Montgomery, Alabama",
      "Montpelier, Vermont",
      "Nashville, Tennessee",
      "Oklahoma City, Oklahoma",
      "Olympia, Washington",
      "Phoenix, Arizona",
      "Pierre, South Dakota",
      "Providence, Rhode Island",
      "Raleigh, North Carolina",
      "Richmond, Virginia",
      "Sacramento, California",
      "Saint Paul, Minnesota",
      "Salem, Oregon",
      "Salt Lake City, Utah",
      "Santa Fe, New Mexico",
      "Springfield, Illinois",
      "Tallahassee, Florida",
      "Topeka, Kansas",
      "Trenton, New Jersey"
    ]
  </script>
</amp-state>

Text input

Next we define the input field. We listen to the input-debounced event for text input. Based on the input, we filter the list of cities and write the result to a new amp-state variable filteredCities. If the input text is empty, we don't want to show suggestions, which we avoid by return an empty array if the input text is empty: event.value.length == 0 ? []: .... We also bind the input value to a variable called city, which we'll use to set the value when the user clicks on a suggestion.

<label>
  Enter city:
  <input [value]="city"
    on="input-debounced: AMP.setState({
              filteredCities: event.value.length == 0 ?
                []:
                cities.filter(city =>
                   city.toLowerCase().indexOf(event.value.toLowerCase()) >= 0
                )
           })">
</label>

Suggestion box

We use amp-selector to make the suggestions selectable. When the user clicks on a suggestions, the select event will be fired and the selected city will be written to the city variable: city: event.targetOption. The filteredCities will be cleared, which also results in the suggestion box being hidden.

The Suggestion box will appear below the input field once the user enters text into the input field. It uses an amp-list to dynamically render the filtered suggestions: [src]="filteredCities".

The list is initially hidden (height="0") and will only be shown when filteredCities is not empty ([height]="filteredCities.length * 34"), where 34 is the height in pixels of a single suggestion.

<amp-selector on="select:AMP.setState({
                        city: event.targetOption,
                        filteredCities: []
                     })"
  keyboard-select-mode="focus">
  <amp-list id="auto-suggest"
    items="."
    layout="fixed-height"
    height="0"
    [src]="filteredCities"
    [height]="filteredCities.length * 34">
    <template type="amp-mustache">
      <div option="{{.}}">{{.}}</div>
    </template>
  </amp-list>
</amp-selector>
Need further explanation?

If the explanations on this page don't cover all of your questions feel free to reach out to other AMP users to discuss your exact use case.

Go to Stack Overflow
An unexplained feature?

The AMP project strongly encourages your participation and contributions! We hope you'll become an ongoing participant in our open source community but we also welcome one-off contributions for the issues you're particularly passionate about.

Edit sample on GitHub