Custom dropdown/auto-complete with AngularJS (Version 2)

It’s been over a year now since I released the version 1 of what I called the Custom Select directive (since it was based on the functionality of the AngularJS select directive).

Unfortunately, the designers of AngularJS decided to change the way the select directive works on version 1.4, thus breaking some of the features of this directive. So I decided to redesign it and use a different (and actually simpler) approach. So what used to be:


<div custom-select ng-model="fruit" ng-options="f for f in fruits">
</div>

is now:


<div custom-select="f for f in fruits | filter: $searchTerm" ng-model="fruit">
</div>

where $searchTerm is a parameter provided by the directive, that corresponds to the text in the search box.

Now the directive delegates the job of filtering to the programmer, letting you use any of the built-in AngularJS filters, or plugging in your own:





<div custom-select="p as p.name for p in findPeople($searchTerm)" ng-model="person">
</div>




And filter synchronously:

$scope.findPeople = function (term) {
    // Suppose we have a people array
    var found = [];
    for (var i = 0; i < people.length; i++) {
        if (/* search all properties you like */) {
            found.push(people[i]);
        }
    }
    return found;
};

Or asynchronously:

$scope.findPeople = function (term) {
    var url = 'http://mysite.com/search?q=' + encodeURIComponent(term);
    return $http.get(url); // This server call must return an array of objects
};

You can check out the new code from the GitHub repository. If you still want to use the previous version, you can find it here.

Happy coding!

12 thoughts on “Custom dropdown/auto-complete with AngularJS (Version 2)

  1. Pingback: Custom dropdown/auto-complete with AngularJS | Axel Zarate
  2. It is creating problem with Safari when we are taking data with asynchronous call. It is not showing data in component. but when we are typing in auto-complete it is reflecting the data. In chrome, it is working fine.

    • Hi, Saurabh.

      For the async call to work, you must return a promise object that, when resolved, produces an array. Built-in AngularJS services already work with the promise pattern, so return $http.get(url); should work.

      You can also construct your own promise objects using the $q service.

      var deferred = $q.defer();
      // At some point in time, you must call deferred.resolve() or deferred.reject()
      return deferred.promise;
      

      If you provide a snippet of the code that is not working for you, I could help you find the problem.

      • Thanks Axelzarate for quick reply. I am doing the same thing and getting the result. But after that I am facing the two issues.

        I want to change the data of component, when I am changing the value of another model or select box as an example, according to states I want to change the cities. So when I am trying to do so, deffered.promise value is changing but it is not reflecting in component. It is looking directive is not refreshing with new data.
        Filter is also not working with asynchronous call, can you give any example or solution for same.

    • This problem has been recently address on the Github repository. Due to the lazy evaluation of (async) filters, the list is not refreshed until you type something in the dropdown searchbox. You can refer to this issue for more details.
      You will need to get the last version of the directive and set the new async option to false (or just don’t set it, the default is false).

      • Thanks Axelzarate , if we fill the collection in button event as example then i need to set ng-model to set selected value id doesn’t work,
        please i need to use these amazing control but i face this proplem
        thanks

  3. Thanks Axelzarate , if we fill the collection in button event as example then i need to set ng-model to set selected value id doesn’t work,
    please i need to use these amazing control but i face this proplem

  4. Hi axelzarate,
    I am trying to use the custom select directive in angular formly getting exception
    “dropdownElement.eq(…).dropdown is not a function” in the directive,
    please let me know the step how can i configure custom select directive in angular formly.
    Thanks.

    • Hi Nmurthy,
      You need to add the script reference to jQuery before Angular. The custom select uses the Bootstrap dropdown plugin, which in turn uses jQuery. If by the time Angular loads jQuery is not defined, it uses jqLite as a replacement and many jQuery functions are not available for elements inside angular directives.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s