Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

typeahead angular ui - cannot read property 'length' of undefined

I am using Angular-ui Bootstrap for my application. I use the typeahead directive.

html:

<input type="text" class="pass_code_input" ng-model="SuppPrefix" Typeahead="ddl_item.Text for ddl_item in getData($viewValue)"/>

Controller

function AutoCompleteCtrl($scope,$http, AutoCompleteSrv) {
    $scope.getData = function (prefix) {
        AutoCompleteSrv.GetAutoComplete("Supplier", prefix).then(function (result) {
            var results_arr = [];
            angular.forEach(result.data, function (item) {
                results_arr.push({ "Val": item.Val, "Text": item.Text });
            });
            return results_arr
        });  
    };
};

service:

    function AutoCompleteSrv($http) {
    var _$http = $http;
    self = this;
    self.GetAutoComplete = function (DataType, Prefix) {
        var promise = _$http({
            method: "GET",
            url: 'api/AutoComplete',
            params: { 'DataType': DataType, 'Prefix': Prefix }
        }).success(function (data, status, headers, config) {

        }).error(function (data, status, headers, config) {

        });
        return promise;
    };
};

I do recieve the data from server, but I can't display it on the screen. When I run debugger in chrome dev tools, I get the next error:

TypeError: Cannot read property 'length' of undefined
at http://localhost:52145/js/libs/ui-bootstrap-tpls-0.11.0.min.js:13:12650
at m.promise.then.u (http://localhost:52145/js/angular/angular.min.js:97:280)
at m.promise.then.u (http://localhost:52145/js/angular/angular.min.js:97:280)
at http://localhost:52145/js/angular/angular.min.js:98:417
at h.$eval (http://localhost:52145/js/angular/angular.min.js:108:482)
at h.$digest (http://localhost:52145/js/angular/angular.min.js:106:62)
at h.$apply (http://localhost:52145/js/angular/angular.min.js:109:287)
at HTMLInputElement.l (http://localhost:52145/js/angular/angular.min.js:133:191)
at http://localhost:52145/js/angular/angular.min.js:31:32
at q (http://localhost:52145/js/angular/angular.min.js:7:386)

I've searched for solution in multiple places, like that, and also followed step by step the instructions in the bootstrap ui home page. What did I do wrong?

like image 375
HS1 Avatar asked Jul 06 '14 11:07

HS1


2 Answers

I just ran into this and just solved it. The key here is that in the example given on the angular site they "return" the $http results. That makes it confusing to look at but ultimately that is the return that matters. So in your case you are setting a variable to that return value so the return never gets returned. When your code is formatted in this way you will need to do 2 things to change it: The first is that the "return" statement is in the wrong place. The second is that the declaration for the returned value is also in the wrong place. Here is the non-working code from the example:

.....
then(function(res){
      var addresses = [];
      angular.forEach(res.data.results, function(item){
        addresses.push(item.formatted_address);
      });
      return addresses;
    });

Here is how I changed it to get it working.

var addresses = []
....
then(function(res){
      angular.forEach(res.data.results, function(item){
        addresses.push(item.formatted_address);
      });
    });
    return addresses;

This becomes more clear if you do not use the "then" but instead use the "success" and "error" functions. It then becomes obvious where the return statement should lie and where the returned value declaration should be. Writing the code that way and getting it to work is how I figured out the problem. NOTE that you should clear out the addressses value in the "then" function or else it will just keep appending more and more values.

like image 120
Scott Avatar answered Nov 05 '22 02:11

Scott


I was also having this problem.

For me I had my controller calling my service, which was then talking to the api to get my data.

Even though getting the data was working (I was able to see this with a console.log) nothing was being displayed on the webpage to select from, and I was getting the

cannot read property length of undefined 

error.

Finally I realized I needed to return my call to the service.

//controller with code NOT working
vm.getData = function(val, ep) {

  myService.getData(val, ep)
   .then(function(data){
     return data
  });
};

//service

this.getData = function(val, ep) {
  return $http({
    //do http call here
  })
    .then(function(data) {
        //do what's needed with the data here
      return data
    });
};

the fix that got this working:

//controller with code WORKING
vm.getData = function(val, ep) {

 return myService.getData(val, ep)
   .then(function(data){
     return data
  });
};

So again, I just needed to return my call to the service and then the typeahead worked as expected and no more error!

like image 28
jsuser Avatar answered Nov 05 '22 01:11

jsuser