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:

ParameterTypeDefaultDescription
openInstringpageDefines how to open Autocomplete, can be page or popup (for Standalone) or dropdown
sourcefunction (query, render)Function which accepts search query and render function where you need to pass array with matched items
limitnumberLimit number of maximum displayed items in autocomplete per query
preloaderbooleanfalseSet to true to include Preloader to autocomplete layout
preloaderColorstringPreloader color, one of the default colors
valuearrayArray with default selected values
valuePropertystringidName of matched item object's key that represents item value
textPropertystringtextName of matched item object's key that represents item display value which is used as title of displayed options
Standalone Autocomplete Parameters
requestSourceOnOpenbooleanfalseIf enabled, then it will request passed to source function on autocomplete open
openerElstring
HTMLElement
String with CSS selector or HTMLElement of link which will open standalone autocomplete page or popup on click
popupCloseLinkTextstringCloseDefault text for "Close" button when opened as Popup
pageBackLinkTextstringBackDefault text for "Back" link when opened as Page
pageTitlestringAutocomplete 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
popupPushbooleanfalseEnables Autocomplete popup to push view/s behind on open
popupSwipeToClosebooleanundefinedEnables ability to close Autocomplete popup with swipe. When not specified it inherits app's Popup swipeToClose parameter
sheetPushbooleanfalseEnables Autocomplete sheet to push view/s behind on open
sheetSwipeToClosebooleanundefinedEnables ability to close Autocomplete sheet with swipe. When not specified it inherits app's Sheet swipeToClose parameter
searchbarPlaceholderstringSearch...Searchbar placeholder text
searchbarDisableTextstringCancelSearchbar "Cancel" button text
searchbarSpellcheckbooleanfalseSets value of spellcheck attribute on Searchbar's input element
notFoundTextstringNothing foundText which is displayed when no matches found
multiplebooleanfalseSet to true to allow multiple selections
closeOnSelectbooleanfalseSet to true and autocomplete will be closed when user picks value. Not available if multiple is enabled
autoFocusbooleanfalseSet to true to auto focus search field on autocomplete open
animatebooleantrueSet to false to open standalone autocomplete without animation
navbarColorThemestringNavbar color theme. One of the default color themes
formColorThemestringForm (checkboxes or radios) color theme. One of the default color themes
routableModalsbooleantrueWill 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
urlstringselect/Standalone autocomplete URL that will be set as a current route
viewobjectLink to initialized View instance if you want use standalone Autocomplete. By default, if not specified, it will be opened in Main View.
Dropdown Autocomplete Parameters
inputElstring
HTMLElement
String with CSS selector or HTMLElement of related text input
inputEventsstringinputAllows to configure input events used to handle Autocomplete actions and source request. Can be changed for example to change keyup compositionend if you use keyboard with composition of Chinese characters
highlightMatchesbooleantrueHighlight matches in autocomplete results
typeaheadbooleanfalseEnables type ahead, will prefill input value with first item in match
dropdownPlaceholderTextstringSpecify dropdown placeholder text
updateInputValueOnSelectbooleantrueIf true then value of related input will be update as well
expandInputbooleanfalseIf true then input which is used as item-input in List View will be expanded to full screen wide during dropdown visible.
dropdownContainerElstring
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
renderDropdownfunction(items)Function to render autocomplete dropdown, must return dropdown HTML string
renderPagefunction(items)Function to render autocomplete page, must return page HTML string
renderPopupfunction(items)Function to render autocomplete popup, must return popup HTML string
renderItemfunction(item, index)Function to render single autocomplete, must return item HTML string
renderSearchbarfunctionFunction to render searchbar, must return searchbar HTML string
renderNavbarfunctionFunction to render navbar, must return navbar HTML string
Events
onobject

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 autocompletes. 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.paramsObject with passed initialization parameters
autocomplete.valueArray with selected items
autocomplete.openedtrue if Autocomplete is currently opened
autocomplete.openerElHTML element of Autocomplete opener element (if passed on init)
autocomplete.$openerElDom7 instance of of Autocomplete opener element (if passed on init)
autocomplete.inputElHTML element of Autocomplete input (if passed on init)
autocomplete.$inputElDom7 instance of of Autocomplete input (if passed on init)
autocomplete.$dropdownElDom7 instance of Autocomplete dropdown
autocomplete.urlAutocomplete URL (that was passed in url parameter)
autocomplete.viewAutocomplete View (that was passed in view parameter) or found parent view
autocomplete.elHTML element of Autocomplete container: dropdown element, or popup element, or page element. Available when Autocomplete opened
autocomplete.$elDom7 instance of Autocomplete container: dropdown element, or popup element, or page element. Available when Autocomplete opened
autocomplete.searchbarAutocomplete page Searchbar instance
Methods
autocomplete.open()Open Autocomplete (Dropdown, Page or Popup)
autocomplete.close()Close Autocomplete
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.

EventTargetArgumentsDescription
changeautocompleteautocomplete, valueEvent will be triggered when Autocomplete value changed. Returned value is an array with selected items
autocompleteChangeapp
openautocompleteautocompleteEvent will be triggered when Autocomplete starts its opening animation. As an argument event handler receives autocomplete instance
autocompleteOpenapp
openedautocompleteautocompleteEvent will be triggered after Autocomplete completes its opening animation. As an argument event handler receives autocomplete instance
autocompleteOpenedapp
closeautocompleteautocompleteEvent will be triggered when Autocomplete starts its closing animation. As an argument event handler receives autocomplete instance
autocompleteCloseapp
closedautocompleteautocompleteEvent will be triggered after Autocomplete completes its closing animation. As an argument event handler receives autocomplete instance
autocompleteClosedapp
beforeDestroyautocompleteautocompleteEvent will be triggered right before Autocomplete instance will be destroyed. As an argument event handler receives autocomplete instance
autocompleteBeforeDestroyapp

CSS Variables

Below is the list of related CSS variables (CSS custom properties).

Note that commented variables are not specified by default and their values is what they fallback to in this case.

:root {
  --f7-autocomplete-dropdown-placeholder-color: #a9a9a9;
  --f7-autocomplete-dropdown-preloader-size: 20px;
  /*
  --f7-autocomplete-dropdown-selected-bg-color: rgba(var(--f7-theme-color-rgb), 0.2);
  */
  --f7-autocomplete-dropdown-bg-color: #fff;
}
:root .theme-dark,
:root.theme-dark {
  --f7-autocomplete-dropdown-bg-color: #1c1c1d;
}
.ios {
  --f7-autocomplete-dropdown-box-shadow: 0px 3px 3px rgba(0, 0, 0, 0.2);
  --f7-autocomplete-dropdown-text-matching-font-weight: 600;
  --f7-autocomplete-dropdown-font-size: var(--f7-list-font-size);
  --f7-autocomplete-dropdown-text-color: #000;
  --f7-autocomplete-dropdown-text-matching-color: #000;
}
.ios .theme-dark,
.ios.theme-dark {
  --f7-autocomplete-dropdown-text-color: #fff;
  --f7-autocomplete-dropdown-text-matching-color: #fff;
}
.md {
  --f7-autocomplete-dropdown-box-shadow: 0 2px 2px rgba(0, 0, 0, 0.25);
  --f7-autocomplete-dropdown-text-matching-font-weight: 400;
  --f7-autocomplete-dropdown-font-size: var(--f7-list-font-size);
  --f7-autocomplete-dropdown-text-color: rgba(0, 0, 0, 0.54);
  --f7-autocomplete-dropdown-text-matching-color: #212121;
}
.md .theme-dark,
.md.theme-dark {
  --f7-autocomplete-dropdown-text-color: rgba(255, 255, 255, 0.54);
  --f7-autocomplete-dropdown-text-matching-color: rgba(255, 255, 255, 0.87);
}
.aurora {
  --f7-autocomplete-dropdown-box-shadow: 0px 1px 2px rgba(0, 0, 0, 0.2);
  --f7-autocomplete-dropdown-text-matching-font-weight: 700;
  --f7-autocomplete-dropdown-font-size: 13px;
  --f7-autocomplete-dropdown-text-color: #000;
  --f7-autocomplete-dropdown-text-matching-color: #000;
}
.aurora .theme-dark,
.aurora.theme-dark {
  --f7-autocomplete-dropdown-text-color: #fff;
  --f7-autocomplete-dropdown-text-matching-color: #fff;
}

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-bg"></div>
    <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(', '));
    },
  },
});