7

What i'm trying to do is an Angular Material autocomplete (md-autocomplete) with data dynamically retrieved from an AJAX call to my REST API. Unfortunately I get only indeterminate progress bar instead of autocomplete items as you can see below.

Result

enter image description here

Controller

$scope.customersSelect = {};
$scope.selectedItem = null;
$scope.searchText = null;

$scope.getCustomers = function (query) {
    selectsService.getCustomers(query).then(function (results) {
        $scope.customersSelect = results.data;
        console.log($scope.customersSelect);
    }, function(error) {
        alert(error.data.message);
    });
}

Service

var selectsServiceFactory = {};

_getCustomers = function (query) {
    return $http.get(serviceBase + 'api/selects/customers/' + query)
    .then(function(results) {
        return results;
    });
}

selectsServiceFactory.getCustomers = _getCustomers;

return selectsServiceFactory;

View

<md-autocomplete md-floating-label="Klient" 
            autocomplete="off" 
            flex="" 
            md-search-text-change="getCustomers(searchText)" 
            md-item-text="item" 
            md-items="item in customersSelect" 
            md-search-text="searchText" 
            md-selected-item="machine.customerId" 
            md-input-maxlength="100" 
            md-input-minlength="2" 
            md-input-name="machineOwner">
<md-item-template>
    <span md-highlight-text="searchText">{{item}}</span>
</md-item-template> 

I'm getting the data successfully from the API, because I can see it printed in the console.

1
  • Why don't you return a promise from service? Commented Nov 22, 2015 at 12:25

4 Answers 4

13

(function() {
  'use strict';
  angular
    .module('MyApp')
    .controller('DemoCtrl', DemoCtrl);

  function DemoCtrl($http) {
    var self = this;
    
    self.data = null;
    self.selectedItem = null;
    self.searchText = null;
    
    self.querySearch = function (query) {
      $http.get('http://www.omdbapi.com/?s=' + escape(query))
        .then(function(result) {
          self.data = result.data.Search;
          return result.data.Search;
        });
    }
  }
})();
<!DOCTYPE html>
<html >
  <head>
    <meta charset="UTF-8">
    <title>$http md-Autocomplete</title>
    <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700,400italic">
    
    
    <link rel='stylesheet prefetch' href='https://cdn.gitcdn.xyz/cdn/angular/bower-material/v1.0.0-rc4/angular-material.css'>
  </head>

  <body>

    <div class="autocompletedemoFloatingLabel" ng-controller="DemoCtrl as ctrl" ng-app="MyApp" layout="column" ng-cloak="">
      <md-content class="md-padding">
        <form name="searchForm" ng-submit="$event.preventDefault()">
            <div layout-gt-sm="row">
            <md-input-container flex="">
              <label>Name</label>
              <input type="text">
            </md-input-container>
            <md-autocomplete md-floating-label="Favorite movie" 
                            flex="" 
                            md-item-text="item.Title"
                            md-items="item in ctrl.data" 
                            md-search-text-change="ctrl.querySearch(ctrl.searchText)"
                            md-search-text="ctrl.searchText" 
                            md-selected-item="ctrl.selectedItem" 
                            md-no-cache="ctrl.noCache" 
                            md-input-maxlength="30" 
                            md-input-minlength="2" 
                            md-input-name="autocompleteField" 
                            required="">
              <md-item-template>
                <span md-highlight-text="ctrl.searchText">{{item.Title}}</span>
              </md-item-template>
              <div ng-messages="searchForm.autocompleteField.$error" ng-if="searchForm.autocompleteField.$touched">
                <div ng-message="required">You <b>must</b> have a favorite movie.</div>
                <div ng-message="minlength">Your entry is not long enough.</div>
                <div ng-message="maxlength">Your entry is too long.</div>
              </div>
            </md-autocomplete>
          </div>
        </form>
      </md-content>
    </div>
    <script src='https://ajax.googleapis.com/ajax/libs/angularjs/1.4.6/angular.js'></script>
    <script src='https://ajax.googleapis.com/ajax/libs/angularjs/1.4.6/angular-animate.min.js'></script>
    <script src='https://ajax.googleapis.com/ajax/libs/angularjs/1.4.6/angular-route.min.js'></script>
    <script src='https://ajax.googleapis.com/ajax/libs/angularjs/1.4.6/angular-aria.min.js'></script>
    <script src='https://ajax.googleapis.com/ajax/libs/angularjs/1.4.6/angular-messages.min.js'></script>
    <script src='https://cdn.gitcdn.xyz/cdn/angular/bower-material/v1.0.0-rc4/angular-material.js'></script>
    <script src='https://s3-us-west-2.amazonaws.com/s.cdpn.io/t-114/assets-cache.js'></script>    
  </body>
</html>

Finally I have done it. Here is the solution.

Sign up to request clarification or add additional context in comments.

1 Comment

Does this solution have progress bar? @PawelH893
0

I struggled with this as well. I end up doing something like this:

$scope.querySearch=function(searchTerm) {
  return $http({
       url:"http://mysearch.api?keyword="+searchTerm,
       method:"GET"
       })
       .then(function(res) {
          return res.data;
       }
}

Problem for me was that md-autocomplete need the result to be an array, where the response from $http is an object. I hope this help someone else!!

Comments

0

You can use Angularjs promises to get data from $http call.

        <body>
                <form name="searchForm" ng-submit="searchForm.$valid && submit()" novalidate>
                    <md-autocomplete flex-gt-sm="35"
                                required md-input-name="autocompleteField" 
                                md-input-maxlength="80" 
                                md-selected-item="selectedItem"
                                md-search-text="formdata.searchText" 
                                md-items="item in querySearch(formdata.searchText)" 
                                md-item-text="item.display" 
                                md-min-length="0"
                                md-floating-label="Get Values">
                                <md-item-template>
                                  <span md-highlight-text="formdata.searchText" md-highlight-flags="^i">{{item.display}}</span>
                                </md-item-template>
                                <md-not-found>
                                  No data matching "{{formdata.searchText}}" were found.
                                </md-not-found>
                                <div ng-messages="searchForm.autocompleteField.$error" ng-if="searchForm.autocompleteField.$touched">
                                  <div ng-message="required">Please <b>select</b> Pricing model id.</div>
                                </div>
                            </md-autocomplete>
                </form>
             </body>
        <script>
        var getdataList= getData().then(function(greeting) {
                  $scope.getdataList = greeting;
            })
            $scope.querySearch = querySearch;
        function querySearch(query) {
                var results = query ? $scope.getdataList.filter(createFilterFor(query)): $scope.getdataList, deferred;
                    return results;
                }
        function getData() {
                deferred = $q.defer();
                $http.get(url).then(function(response) {
                        var responseList = response.map(function (task) {
                            return {value: task.dataname, display:task.dataname};  
                        });
                        deferred.resolve(responseList);
                    },function myError() {
                        console.log("Error")
                    });
                return deferred.promise;
            }
        function createFilterFor(query) {
                    var lowercaseQuery = query.toLowerCase();
                      return function filterFn(state) {
                        var lowercaseState = state.value.toLowerCase();
                      return (lowercaseState.search(lowercaseQuery) >= 0);
                    };
                }


        </script>

Comments

-1

Use $apply to kick a digest cycle yourself, it will update the view.

$scope.getCustomers = function (query) {
selectsService.getCustomers(query).then(function (results) {
    $scope.customersSelect = results.data;
    $scope.$apply();
    console.log($scope.customersSelect);
}, function(error) {
    alert(error.data.message);
});
}

3 Comments

Now it's giving me an error $digest already in progress link. I think it's beacuse $scope.$apply() is called in the onChange event.
do something like setTimeout(function(){ $scope.$apply(); }, 200);
It didn't help either. The error $digest already in progress no longer occurs but the autocomplete still doesn't show.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.