Search code examples
javascriptangularjsajaxangular-ui-typeahead

AngularJS typeahead giving [filter:notarray] error on Ajax GET query


I have an AngularJS 1.4.7 typeahead:

<input type="text" 
       class="form-control simpleinput"
       placeholder="keyword" 
       name="searchbarFormInput"
       id="searchbarFormInput" 
       ng-model="selected" 
       ng-click="selected=null"
       ng-enter="doBlur($event)"
       uib-typeahead="record.display_name for record in getRecords($viewValue) | filter:{ display_name : $viewValue }"
       typeahead-template-url="searchbar-result-template.html"
       typeahead-on-select="selectRecord($item)"
       typeahead-focus-on-select="false"
       typeahead-editable="false"
       autocomplete="off" /> 

This typeahead's controller calls getRecords(needle) and filters on the provided needle value ($viewValue, or whatever value is in the input view):

$scope.getRecords = function(needle) {
    return $scope.testRecords;
}

Here, $scope.testRecords is an array of test objects, e.g.:

$scope.testRecords = [ { "display_name" : "foo" } , { "display_name" : "bar" } ... ];

This works correctly. The typeahead will render a pulldown menu. The menu is filtered based on what I type into the input field.

Now I want to source this array of records from a GET query:

$scope.getRecords = function(needle) {
    return $http.get('/search/by', {
        params: {
            'requestType' : 'searchByDisplayName',
            'pageSize' : 1000
        }
    }).then(function(res) {
        console.log(res.data.results);
        return res.data.results;
    });
}

This is a GET request to a route that works when called directly (confirmed via, for example, curl or wget).

Also, when I look at the browser console, console.log(res.data.results) shows the correct array of objects — the exact same objects that are in the array $scope.testObjects.

However, I get no pulldown menu and I also get the following [filter:notarray] error:

Error: [filter:notarray] http://errors.angularjs.org/1.4.7/filter/notarray?p0=%7B%22%24%24state%22%3A%7B%22status%22%3A0%7D%7D
https://ajax.googleapis.com/ajax/libs/angularjs/1.4.7/angular.min.js:6:421
https://ajax.googleapis.com/ajax/libs/angularjs/1.4.7/angular.min.js:149:197
fn
R@https://cdnjs.cloudflare.com/ajax/libs/angular-ui-bootstrap/0.14.3/ui-bootstrap-tpls.min.js:11:6694
https://cdnjs.cloudflare.com/ajax/libs/angular-ui-bootstrap/0.14.3/ui-bootstrap-tpls.min.js:11:8633
$$parseAndValidate@https://ajax.googleapis.com/ajax/libs/angularjs/1.4.7/angular.min.js:263:425
$commitViewValue@https://ajax.googleapis.com/ajax/libs/angularjs/1.4.7/angular.min.js:263:284
https://ajax.googleapis.com/ajax/libs/angularjs/1.4.7/angular.min.js:265:279
$eval@https://ajax.googleapis.com/ajax/libs/angularjs/1.4.7/angular.min.js:133:221
$apply@https://ajax.googleapis.com/ajax/libs/angularjs/1.4.7/angular.min.js:133:456
$$debounceViewValueCommit@https://ajax.googleapis.com/ajax/libs/angularjs/1.4.7/angular.min.js:265:249
$setViewValue@https://ajax.googleapis.com/ajax/libs/angularjs/1.4.7/angular.min.js:264:507
l@https://ajax.googleapis.com/ajax/libs/angularjs/1.4.7/angular.min.js:163:165
c@https://ajax.googleapis.com/ajax/libs/angularjs/1.4.7/angular.min.js:35:221

This error repeats for as many letters as I enter into the input field.

What am I doing wrong with the request, typeahead, or typeahead filter, and how can I fix this?


Solution

  • In your code that doesn't work you're returning a promise (the result of .then()), not the array:

    res.data.results
    

    Edit: https://github.com/angular-ui/bootstrap/blob/master/src/typeahead/typeahead.js#L219

    Expects the result of the expression to yield an array and not a promise. In other words, you should use the change event to trigger the function that updates your array via a promise, but the 'for record in nameOfAnArray' portion of the expression should not be the function. It should be a variable on the $scope. When it changes it should trigger the digest and update.