Autocomplete

Framework7 comes with mobile-friendly and touch optimized Autocomplete component.

Autocomplete could be used in standalone mode or as a dropdown.

Autocomplete App Methods

Autocomplete can be created and initialized only using JavaScript. We need to use related App's method:

app.autocomplete.create(parameters)- create Autocomplete instance

  • parameters - object. Object with autocomplete parameters

Method returns created Autocomplete's instance

app.autocomplete.destroy(el)- destroy Autocomplete instance

  • el - HTMLElement or string (with CSS Selector) or object. Autocomplete instance to destroy.

app.autocomplete.get(el)- get Autocomplete instance by HTML element

  • el - HTMLElement or string (with CSS Selector). Autocomplete element.

Method returns Autocomplete's instance

app.autocomplete.open(el)- open Autocomplete

  • el - HTMLElement or string (with CSS Selector). Autocomplete element to open.

Method returns Autocomplete's instance

app.autocomplete.close(el)- closes Autocomplete

  • el - HTMLElement or string (with CSS Selector). Autocomplete element to close.

Method returns Autocomplete's instance

For example:

var autocomplete = app.autocomplete.create({
  inputEl: '#autocomplete-dropdown',
  openIn: 'dropdown',
  source: function (query, render) {
    ...
  }
});

Autocomplete Parameters

Let's look on list of all available parameters:

Parameter Type Default Description
openIn string page Defines how to open Autocomplete, can be page or popup (for Standalone) or dropdown
source function (query, render) Function which accepts search query and render function where you need to pass array with matched items
limit number Limit number of maximum displayed items in autocomplete per query
preloader boolean false Set to true to include Preloader to autocomplete layout
preloaderColor string Preloader color, one of the default colors
value array Array with default selected values
valueProperty string id Name of matched item object's key that represents item value
textProperty string text Name of matched item object's key that represents item display value which is used as title of displayed options
Standalone Autocomplete Parameters
requestSourceOnOpen boolean false If enabled, then it will request passed to source function on autocomplete open
openerEl string
HTMLElement
String with CSS selector or HTMLElement of link which will open standalone autocomplete page or popup on click
popupCloseLinkText string Close Default text for "Close" button when opened as Popup
pageBackLinkText string Back Default text for "Back" link when opened as Page
pageTitle string Autocomplete page title. If nothing is specified and passed openerEl is an item of List View, then text value of item-title element will be used
searchbarPlaceholder string Search... Searchbar placeholder text
searchbarDisableText string Cancel Searchbar "Cancel" button text
notFoundText string Nothing found Text which is displayed when no matches found
multiple boolean false Set to true to allow multiple selections
closeOnSelect boolean false Set to true and autocomplete will be closed when user picks value. Not available if multiple is enabled
autoFocus boolean false Set to true to auto focus search field on autocomplete open
animate boolean true Set to false to open standalone autocomplete without animation
navbarColorTheme string Navbar color theme. One of the default color themes
formColorTheme string Form (checkboxes or radios) color theme. One of the default color themes
routableModals boolean true Will add opened autocomplete modal (when openIn: 'popup') to router history which gives ability to close autocomplete by going back in router history and set current route to the autocomplete modal
url string select/ Standalone autocomplete URL that will be set as a current route
view object Link to initialized View instance if you want use standalone Autcomplete. By default, if not specified, it will be opened in Main View.
Dropdown Autocomplete Parameters
inputEl string
HTMLElement
String with CSS selector or HTMLElement of related text input
inputEvents string input Allows to configure input events used to handle Autcomplete actions and source request. Can be changed for example to change keyup compositionend if you use keyboard with composition of Chinese characters
highlightMatches boolean true Highlight matches in autcomplete results
typeahead boolean false Enables type ahead, will prefill input value with first item in match
dropdownPlaceholderText string Specify dropdown placeholder text
updateInputValueOnSelect boolean true If true then value of related input will be update as well
expandInput boolean false If true then input which is used as item-input in List View will be expanded to full screen wide during dropdown visible.
dropdownContainerEl string
HTMLElement
By default dropdown will be added to parent page-content element. You can specify here different element where to add dropdown element
Render functions
renderDropdown function(items) Function to render autocomplete dropdown, must return dropdown HTML string
renderPage function(items) Function to render autocomplete page, must return page HTML string
renderPopup function(items) Function to render autocomplete popup, must return popup HTML string
renderItem function(item, index) Function to render single autocomplete, must return item HTML string
renderSearchbar function Function to render searchbar, must return searchbar HTML string
renderNavbar function Function to render navbar, must return navbar HTML string
Events
on object Object with events handlers. For example:
var autocomplete = app.autocomplete.create({
  ...
  on: {
    opened: function () {
      console.log('Autocomplete opened')
    }
  }
})

Note that all following parameters can be used in global app parameters under autocomplete property to set defaults for all autcompletes. For example:

var app = new Framework7({
  autocomplete: {
    openIn: 'popup',
    animate: false,
  }
});

Autocomplete Methods & Properties

After we initialize Autocomplete we have its initialized instance in variable (like autocomplete variable in example above) with helpful methods and properties:

Properties
autocomplete.params Object with passed initialization parameters
autocomplete.value Array with selected items
autocomplete.opened true if Autocomplete is currently opened
autocomplete.openerEl HTML element of Autcomplete opener element (if passed on init)
autocomplete.$openerEl Dom7 instance of of Autcomplete opener element (if passed on init)
autocomplete.inputEl HTML element of Autcomplete input (if passed on init)
autocomplete.$inputEl Dom7 instance of of Autcomplete input (if passed on init)
autocomplete.$dropdownEl Dom7 instance of Autcomplete dropdown
autocomplete.url Autcomplete URL (that was passed in url parameter)
autocomplete.view Autcomplete View (that was passed in view parameter) or found parent view
autocomplete.el HTML element of Autcomplete container: dropdown element, or popup element, or page element. Available when Autocomplete opened
autocomplete.$el Dom7 instance of Autcomplete container: dropdown element, or popup element, or page element. Available when Autocomplete opened
autocomplete.searchbar Autcomplete page Searchbar instance
Methods
autocomplete.open() Open Autocomplete (Dropdown, Page or Popup)
autocomplete.close() Close Autcomplete
autocomplete.preloaderShow() Show autocomplete preloader
autocomplete.preloaderHide() Hide autocomplete preloader
autocomplete.destroy() Destroy Autocomplete instance and remove all events
autocomplete.on(event, handler) Add event handler
autocomplete.once(event, handler) Add event handler that will be removed after it was fired
autocomplete.off(event, handler) Remove event handler
autocomplete.off(event) Remove all handlers for specified event
autocomplete.emit(event, ...args) Fire event on instance

Autocomplete Events

Autocomplete instance emits events on both self instance and app instance. App instance events has same names prefixed with autocomplete.

Event Target Arguments Description
change autocomplete autocomplete, value Event will be triggered when Autocomplete value changed. Returned value is an array with selected items
autocompleteChange app
open autocomplete autocomplete Event will be triggered when Autocomplete starts its opening animation. As an argument event handler receives autocomplete instance
autocompleteOpen app
opened autocomplete autocomplete Event will be triggered after Autocomplete completes its opening animation. As an argument event handler receives autocomplete instance
autocompleteOpened app
close autocomplete autocomplete Event will be triggered when Autocomplete starts its closing animation. As an argument event handler receives autocomplete instance
autocompleteClose app
closed autocomplete autocomplete Event will be triggered after Autocomplete completes its closing animation. As an argument event handler receives autocomplete instance
autocompleteClosed app
beforeDestroy autocomplete autocomplete Event will be triggered right before Autocomplete instance will be destroyed. As an argument event handler receives autocomplete instance
autocompleteBeforeDestroy app

Examples

var app = new Framework7();

var $$ = Dom7;

// Fruits data demo array
var fruits = ('Apple Apricot Avocado Banana Melon Orange Peach Pear Pineapple').split(' ');

Simple Dropdown Autocomplete

<div class="list no-hairlines-md">
  <div class="block-header">Simple Dropdown Autocomplete</div>
  <ul>
    <li class="item-content item-input inline-label">
      <div class="item-inner">
        <div class="item-title item-label">Fruit</div>
        <div class="item-input-wrap">
          <input id="autocomplete-dropdown" type="text" placeholder="Fruit">
        </div>
      </div>
    </li>
  </ul>
</div>
var autocompleteDropdownSimple = app.autocomplete.create({
  inputEl: '#autocomplete-dropdown',
  openIn: 'dropdown',
  source: function (query, render) {
    var results = [];
    if (query.length === 0) {
      render(results);
      return;
    }
    // Find matched items
    for (var i = 0; i < fruits.length; i++) {
      if (fruits[i].toLowerCase().indexOf(query.toLowerCase()) >= 0) results.push(fruits[i]);
    }
    // Render items by passing array with result items
    render(results);
  }
});

Dropdown With Input Expand

<div class="list no-hairlines-md">
  <div class="block-header">Dropdown With Input Expand</div>
  <ul>
    <li class="item-content item-input inline-label">
      <div class="item-inner">
        <div class="item-title item-label">Fruit</div>
        <div class="item-input-wrap">
          <input id="autocomplete-dropdown-expand" type="text" placeholder="Fruit">
        </div>
      </div>
    </li>
  </ul>
</div>
var autocompleteDropdownExpand = app.autocomplete.create({
  inputEl: '#autocomplete-dropdown-expand',
  openIn: 'dropdown',
  expandInput: true, // expand input
  source: function (query, render) {
    var results = [];
    if (query.length === 0) {
      render(results);
      return;
    }
    // Find matched items
    for (var i = 0; i < fruits.length; i++) {
      if (fruits[i].toLowerCase().indexOf(query.toLowerCase()) >= 0) results.push(fruits[i]);
    }
    // Render items by passing array with result items
    render(results);
  }
});

Dropdown With All Values

<div class="list no-hairlines-md">
  <div class="block-header">Dropdown With All Values</div>
  <ul>
    <li class="item-content item-input">
      <div class="item-inner">
        <div class="item-title item-label">Fruit</div>
        <div class="item-input-wrap">
          <input id="autocomplete-dropdown-all" type="text" placeholder="Fruit">
        </div>
      </div>
    </li>
  </ul>
</div>
var autocompleteDropdownAll = app.autocomplete.create({
  inputEl: '#autocomplete-dropdown-all',
  openIn: 'dropdown',
  source: function (query, render) {
    var results = [];
    // Find matched items
    for (var i = 0; i < fruits.length; i++) {
      if (fruits[i].toLowerCase().indexOf(query.toLowerCase()) >= 0) results.push(fruits[i]);
    }
    // Render items by passing array with result items
    render(results);
  }
});

Dropdown With Placeholder

<div class="list no-hairlines-md">
  <div class="block-header">Dropdown With Placeholder</div>
  <ul>
    <li class="item-content item-input">
      <div class="item-inner">
        <div class="item-title item-label">Fruit</div>
        <div class="item-input-wrap">
          <input id="autocomplete-dropdown-placeholder" type="text" placeholder="Fruit">
        </div>
      </div>
    </li>
  </ul>
</div>
var autocompleteDropdownPlaceholder = app.autocomplete.create({
  inputEl: '#autocomplete-dropdown-placeholder',
  openIn: 'dropdown',
  dropdownPlaceholderText: 'Try to type "Apple"',
  source: function (query, render) {
    var results = [];
    if (query.length === 0) {
      render(results);
      return;
    }
    // Find matched items
    for (var i = 0; i < fruits.length; i++) {
      if (fruits[i].toLowerCase().indexOf(query.toLowerCase()) >= 0) results.push(fruits[i]);
    }
    // Render items by passing array with result items
    render(results);
  }
});

Dropdown With Typeahead

<div class="list no-hairlines-md">
  <div class="block-header">Dropdown With Typeahead</div>
  <ul>
    <li class="item-content item-input">
      <div class="item-inner">
        <div class="item-title item-label">Fruit</div>
        <div class="item-input-wrap">
          <input id="autocomplete-dropdown-typeahead" type="text" placeholder="Fruit">
        </div>
      </div>
    </li>
  </ul>
</div>
var autocompleteDropdownTypeahead = app.autocomplete.create({
  inputEl: '#autocomplete-dropdown-typeahead',
  openIn: 'dropdown',
  dropdownPlaceholderText: 'Try to type "Pineapple"',
  typeahead: true,
  source: function (query, render) {
    var results = [];
    if (query.length === 0) {
      render(results);
      return;
    }
    // Find matched items
    for (var i = 0; i < fruits.length; i++) {
      if (fruits[i].toLowerCase().indexOf(query.toLowerCase()) === 0) results.push(fruits[i]);
    }
    // Render items by passing array with result items
    render(results);
  }
});

Dropdown With Ajax-Data

<div class="list no-hairlines-md">
  <div class="block-header">Dropdown With Ajax-Data</div>
  <ul>
    <li class="item-content item-input">
      <div class="item-inner">
        <div class="item-title item-label">Language</div>
        <div class="item-input-wrap">
          <input id="autocomplete-dropdown-ajax" type="text" placeholder="Language">
        </div>
      </div>
    </li>
  </ul>
</div>
var autocompleteDropdownAjax = app.autocomplete.create({
  inputEl: '#autocomplete-dropdown-ajax',
  openIn: 'dropdown',
  preloader: true, //enable preloader
  /* If we set valueProperty to "id" then input value on select will be set according to this property */
  valueProperty: 'name', //object's "value" property name
  textProperty: 'name', //object's "text" property name
  limit: 20, //limit to 20 results
  dropdownPlaceholderText: 'Try "JavaScript"',
  source: function (query, render) {
    var autocomplete = this;
    var results = [];
    if (query.length === 0) {
      render(results);
      return;
    }
    // Show Preloader
    autocomplete.preloaderShow();

    // Do Ajax request to Autocomplete data
    app.request({
      url: 'autocomplete-languages.json',
      method: 'GET',
      dataType: 'json',
      //send "query" to server. Useful in case you generate response dynamically
      data: {
        query: query,
      },
      success: function (data) {
        // Find matched items
        for (var i = 0; i < data.length; i++) {
          if (data[i].name.toLowerCase().indexOf(query.toLowerCase()) >= 0) results.push(data[i]);
        }
        // Hide Preoloader
        autocomplete.preloaderHide();
        // Render items by passing array with result items
        render(results);
      }
    });
  }
});

Dropdown With Ajax-Data + Typeahead

<div class="list no-hairlines-md">
  <div class="block-header">Dropdown With Ajax-Data + Typeahead</div>
  <ul>
    <li class="item-content item-input">
      <div class="item-inner">
        <div class="item-title item-label">Language</div>
        <div class="item-input-wrap">
          <input id="autocomplete-dropdown-ajax-typeahead" type="text" placeholder="Language">
        </div>
      </div>
    </li>
  </ul>
</div>
var autocompleteDropdownAjaxTypeahead = app.autocomplete.create({
  inputEl: '#autocomplete-dropdown-ajax-typeahead',
  openIn: 'dropdown',
  preloader: true, //enable preloader
  /* If we set valueProperty to "id" then input value on select will be set according to this property */
  valueProperty: 'name', //object's "value" property name
  textProperty: 'name', //object's "text" property name
  limit: 20, //limit to 20 results
  typeahead: true,
  dropdownPlaceholderText: 'Try "JavaScript"',
  source: function (query, render) {
    var autocomplete = this;
    var results = [];
    if (query.length === 0) {
      render(results);
      return;
    }
    // Show Preloader
    autocomplete.preloaderShow();

    // Do Ajax request to Autocomplete data
    app.request({
      url: 'autocomplete-languages.json',
      method: 'GET',
      dataType: 'json',
      //send "query" to server. Useful in case you generate response dynamically
      data: {
        query: query,
      },
      success: function (data) {
        // Find matched items
        for (var i = 0; i < data.length; i++) {
          if (data[i].name.toLowerCase().indexOf(query.toLowerCase()) === 0) results.push(data[i]);
        }
        // Hide Preoloader
        autocomplete.preloaderHide();
        // Render items by passing array with result items
        render(results);
      }
    });
  }
});

Searchbar Dropdown

<div class="page">
  <div class="navbar">
    <div class="navbar-inner sliding">
      ...
      <!-- Put searchbar in subnavbar -->
      <div class="subnavbar">
        <form class="searchbar" id="searchbar-autocomplete">
          <div class="searchbar-inner">
            <div class="searchbar-input-wrap">
              <input type="search" placeholder="Search">
              <i class="searchbar-icon"></i>
              <span class="input-clear-button"></span>
            </div>
            <span class="searchbar-disable-button">Cancel</span>
          </div>
        </form>
      </div>
    </div>
  </div>
  ...
</div>
var searchbar = app.searchbar.create({
  el: '#searchbar-autocomplete',
  customSearch: true,
  on: {
    search: function (query) {
      console.log(query);
    }
  }
});
var autocompleteSearchbar = app.autocomplete.create({
  openIn: 'dropdown',
  inputEl: '#searchbar-autocomplete input[type="search"]',
  dropdownPlaceholderText: 'Type "Apple"',
  source: function (query, render) {
    var results = [];
    if (query.length === 0) {
      render(results);
      return;
    }
    // Find matched items
    for (var i = 0; i < fruits.length; i++) {
      if (fruits[i].toLowerCase().indexOf(query.toLowerCase()) >= 0) results.push(fruits[i]);
    }
    // Render items by passing array with result items
    render(results);
  }
})

Simple Standalone Autocomplete

div class="list">
  <div class="block-header">Simple Standalone Autocomplete</div>
  <ul>
    <li>
      <a class="item-link item-content" href="#" id="autocomplete-standalone">
        <input type="hidden">
        <div class="item-inner">
          <div class="item-title">Favorite Fruite</div>
          <div class="item-after"></div>
        </div>
      </a>
    </li>
  </ul>
</div>
var autocompleteStandaloneSimple = app.autocomplete.create({
  openIn: 'page', //open in page
  openerEl: '#autocomplete-standalone', //link that opens autocomplete
  closeOnSelect: true, //go back after we select something
  source: function (query, render) {
    var results = [];
    if (query.length === 0) {
      render(results);
      return;
    }
    // Find matched items
    for (var i = 0; i < fruits.length; i++) {
      if (fruits[i].toLowerCase().indexOf(query.toLowerCase()) >= 0) results.push(fruits[i]);
    }
    // Render items by passing array with result items
    render(results);
  },
  on: {
    change: function (value) {
      console.log(value);
      // Add item text value to item-after
      $$('#autocomplete-standalone').find('.item-after').text(value[0]);
      // Add item value to input value
      $$('#autocomplete-standalone').find('input').val(value[0]);
    },
  },
});

Popup Autocomplete

<div class="list">
  <div class="block-header">Popup Autocomplete</div>
  <ul>
    <li>
      <a class="item-link item-content" href="#" id="autocomplete-standalone-popup">
        <input type="hidden">
        <div class="item-inner">
          <div class="item-title">Favorite Fruite</div>
          <div class="item-after"></div>
        </div>
      </a>
    </li>
  </ul>
</div>
var autocompleteStandalonePopup = app.autocomplete.create({
  openIn: 'popup', //open in page
  openerEl: '#autocomplete-standalone-popup', //link that opens autocomplete
  closeOnSelect: true, //go back after we select something
  source: function (query, render) {
    var results = [];
    if (query.length === 0) {
      render(results);
      return;
    }
    // Find matched items
    for (var i = 0; i < fruits.length; i++) {
      if (fruits[i].toLowerCase().indexOf(query.toLowerCase()) >= 0) results.push(fruits[i]);
    }
    // Render items by passing array with result items
    render(results);
  },
  on: {
    change: function (value) {
      // Add item text value to item-after
      $$('#autocomplete-standalone-popup').find('.item-after').text(value[0]);
      // Add item value to input value
      $$('#autocomplete-standalone-popup').find('input').val(value[0]);
    },
  },
});

Multiple Values

<div class="list">
  <div class="block-header">Multiple Values</div>
  <ul>
    <li>
      <a class="item-link item-content" href="#" id="autocomplete-standalone-multiple">
        <input type="hidden">
        <div class="item-inner">
          <div class="item-title">Favorite Fruite</div>
          <div class="item-after"></div>
        </div>
      </a>
    </li>
  </ul>
</div>
var autocompleteStandaloneMultiple = app.autocomplete.create({
  openIn: 'page', //open in page
  openerEl: '#autocomplete-standalone-multiple', //link that opens autocomplete
  multiple: true, //allow multiple values
  source: function (query, render) {
    var autocomplete = this;
    var results = [];
    if (query.length === 0) {
      render(results);
      return;
    }
    // Find matched items
    for (var i = 0; i < fruits.length; i++) {
      if (fruits[i].toLowerCase().indexOf(query.toLowerCase()) >= 0) results.push(fruits[i]);
    }
    // Render items by passing array with result items
    render(results);
  },
  on: {
    change: function (value) {
      // Add item text value to item-after
      $$('#autocomplete-standalone-multiple').find('.item-after').text(value.join(', '));
      // Add item value to input value
      $$('#autocomplete-standalone-multiple').find('input').val(value.join(', '));
    }
  }
});

Standalone With Ajax-Data

<div class="list">
  <div class="block-header">With Ajax-Data</div>
  <ul>
    <li>
      <a class="item-link item-content" href="#" id="autocomplete-standalone-ajax">
        <input type="hidden">
        <div class="item-inner">
          <div class="item-title">Language</div>
          <div class="item-after"></div>
        </div>
      </a>
    </li>
  </ul>
</div>
var autocompleteStandaloneAjax = app.autocomplete.create({
  openIn: 'page', //open in page
  openerEl: '#autocomplete-standalone-ajax', //link that opens autocomplete
  multiple: true, //allow multiple values
  valueProperty: 'id', //object's "value" property name
  textProperty: 'name', //object's "text" property name
  limit: 50,
  preloader: true, //enable preloader
  source: function (query, render) {
    var autocomplete = this;
    var results = [];
    if (query.length === 0) {
      render(results);
      return;
    }
    // Show Preloader
    autocomplete.preloaderShow();
    // Do Ajax request to Autocomplete data
    app.request({
      url: 'autocomplete-languages.json',
      method: 'GET',
      dataType: 'json',
      //send "query" to server. Useful in case you generate response dynamically
      data: {
        query: query
      },
      success: function (data) {
        // Find matched items
        for (var i = 0; i < data.length; i++) {
          if (data[i].name.toLowerCase().indexOf(query.toLowerCase()) >= 0) results.push(data[i]);
        }
        // Hide Preoloader
        autocomplete.preloaderHide();
        // Render items by passing array with result items
        render(results);
      }
    });
  },
  on: {
    change: function (value) {
      var itemText = [],
          inputValue = [];
      for (var i = 0; i < value.length; i++) {
        itemText.push(value[i].name);
        inputValue.push(value[i].id);
      }
      // Add item text value to item-after
      $$('#autocomplete-standalone-ajax').find('.item-after').text(itemText.join(', '));
      // Add item value to input value
      $$('#autocomplete-standalone-ajax').find('input').val(inputValue.join(', '));
    },
  },
});