Angularjs autocomplete from $http
Asked Answered
H

5

61

I'm trying to write an autocomplete directive that fetches data from the server using an $http request (without using any external plugins or scripts). Currently it works only with static data. Now, I know that I need to insert my $http request into the source: of the directive, but I can't find any good documentation on the subject.

http request

$http.post($scope.url, { "command": "list category() names"}). 
            success(function(data, status) {
                $scope.status = status;
                $scope.names = data;    
            })
            .
            error(function(data, status) {
                $scope.data = data || "Request failed";
                $scope.status = status;   
            });

Directive

app.directive('autoComplete', function($timeout) {
    return function(scope, iElement, iAttrs) {
            iElement.autocomplete({
                source: scope[iAttrs.uiItems],
                select: function() {
                    $timeout(function() {
                      iElement.trigger('input');
                    }, 0);
                }
            });
        };
    });

View

<input auto-complete ui-items="names" ng-init="manualcat='no category entered'" ng-model="manualcat"> 

So, how do I piece this all together correctly the Angular way?

Handtomouth answered 27/8, 2013 at 8:16 Comment(2)
Can you provide the full example source code? I just want to know at what time you actually make the HTTP call. Thanks in advance.Skelly
have you found the solution? i'm facing the same problem, seems like $scope.names is empty when directive is loaded, the ajax call is left behindPomander
R
45

I made an autocomplete directive and uploaded it to GitHub. It should also be able to handle data from an HTTP-Request.

Here's the demo: http://justgoscha.github.io/allmighty-autocomplete/ And here the documentation and repository: https://github.com/JustGoscha/allmighty-autocomplete

So basically you have to return a promise when you want to get data from an HTTP request, that gets resolved when the data is loaded. Therefore you have to inject the $qservice/directive/controller where you issue your HTTP Request.

Example:

function getMyHttpData(){
  var deferred = $q.defer();
  $http.jsonp(request).success(function(data){
    // the promise gets resolved with the data from HTTP
    deferred.resolve(data);
  });
  // return the promise
  return deferred.promise;
}

I hope this helps.

Robustious answered 19/12, 2013 at 17:0 Comment(8)
This is throwing an error for me on the template html file that you included in the download. Is this required? If so you may want to make that obvious in the documentationLactoprotein
Does it require all data to be fetched to memory? What if I have 10M+ variants? :)Inheritable
@Inheritable download first 20 what match your criteriaVibrant
any attribute to limit the no of results?Smell
Does this have a timeout you can set, for example... do an http request once you've stopped typing for 1 second? I don't want it to make a request on every key pressed... @JustGoschaPilotage
@JustGoscha please help me for this question : #31579275Noctilucent
I was able to install it. But the select options / matching results are showing behind the next list item. Any way to move them to front? I am looking for an experience similar to NGAutcomplete.Auvil
@justgoscha , what's the best way to add a spinner (loading animation ) to this?Odelle
G
37

Use angular-ui-bootstrap's typehead.

It had great support for $http and promises. Also, it doesn't include any JQuery at all, pure AngularJS.

(I always prefer using existing libraries and if they are missing something to open an issue or pull request, much better then creating your own again)

Gathers answered 7/10, 2013 at 14:24 Comment(3)
Thanks for the answer Urigo. But, like I said in my question, I'm trying to avoid using any external scripts. I'm looking for a pure angular solution. Cheers, GidonHandtomouth
keep in mind that as of today Typeahead in angular-ui-bootstrap ist not compatible with Angular 1.3Emerick
How to get id on select.Repurchase
C
17

You need to write a controller with ng-change function in scope. In ng-change callback you do a call to server and update completions. Here is a stub (without $http as this is a plunk):

HTML

<!doctype html>
<html ng-app="plunker">
    <head>
        <script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.0.5/angular.js"></script>
        <script src="http://angular-ui.github.io/bootstrap/ui-bootstrap-tpls-0.4.0.js"></script>
        <script src="example.js"></script>
        <link href="//netdna.bootstrapcdn.com/twitter-bootstrap/2.3.1/css/bootstrap-combined.min.css" rel="stylesheet">
    </head>
    <body>
        <div class='container-fluid' ng-controller="TypeaheadCtrl">
            <pre>Model: {{selected| json}}</pre>
            <pre>{{states}}</pre>
            <input type="text" ng-change="onedit()" ng-model="selected" typeahead="state for state in states | filter:$viewValue">
        </div>
    </body>
</html>

JS

angular.module('plunker', ['ui.bootstrap']);

function TypeaheadCtrl($scope) {
  $scope.selected = undefined;
  $scope.states = [];

  $scope.onedit = function(){
    $scope.states = [];

    for(var i = 0; i < Math.floor((Math.random()*10)+1); i++){
      var value = "";

      for(var j = 0; j < i; j++){
        value += j;
      }
      $scope.states.push(value);
    }
  }
}
Cysticercus answered 27/8, 2013 at 17:34 Comment(2)
Thanks for the answer madhead. But, like I said in my question, I'm trying to avoid using any external scripts. In your answer you are using the angular-ui bootstrap script. I'm looking for a pure angular solution. Cheers, GidonHandtomouth
I'm using angular-ui for typeahead directive (autocomplete itself).Cysticercus
M
6

the easiest way to do that in angular or angularjs without external modules or directives is using list and datalist HTML5. You just get a json and use ng-repeat for feeding the options in datalist. The json you can fetch it from ajax.

in this example:

  • ctrl.query is the query that you enter when you type.
  • ctrl.msg is the message that is showing in the placeholder
  • ctrl.dataList is the json fetched

then you can add filters and orderby in the ng-reapet

!! list and datalist id must have the same name !!

 <input type="text" list="autocompleList" ng-model="ctrl.query" placeholder={{ctrl.msg}}>
<datalist id="autocompleList">
        <option ng-repeat="Ids in ctrl.dataList value={{Ids}}  >
</datalist>

UPDATE : is native HTML5 but be carreful with the type browser and version. check it out : https://caniuse.com/#search=datalist.

Masto answered 10/7, 2017 at 13:20 Comment(0)
A
0

I found this link helpful

$scope.loadSkillTags = function (query) {
var data = {qData: query};
   return SkillService.querySkills(data).then(function(response) {
   return response.data;
  });
 };
Afterward answered 12/7, 2016 at 3:33 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.