Search code examples
angularjsautocompleteangular-ui-bootstrapangular-ui-typeahead

Asynchronous Angular-bootsrap-UI typeahead: select directive issue


My application is using the Angular-Bootstrap-UI-Typeahead feature for auto complete.

As the user types, i'd like to be able to call an API & return similar strings.

I've followed the guidance here, and everything works fine with the out of box Google API.

I've also successfully swapped in my own API: I am able to call the API, get the data, and log it in the correct format in my browser console.

However, I constantly get "no results found" from the text box. I suspect this may be a problem with the select directive, but i am stumped.

I would greatly appreciate any guidance on this!

Here is some code:

UI (content.html)

<h4>biz results</h4>
<pre>Model: {{user.orgName | json}}</pre>
<input type="text" 
ng-model="user.orgName" 
placeholder="Locations loaded via $http" 
uib-typeahead="obj for obj in getLocation($viewValue)" 
typeahead-loading="loadingBiz" 
typeahead-no-results="noBiz" class="form-control"
typeahead-wait-ms="700">
<i ng-show="loadingBiz" class="glyphicon glyphicon-refresh"></i>
<div ng-show="noBiz">
<i class="glyphicon glyphicon-remove"></i> No Results Found
</div>

Angular (script.js)

$scope.getLocation = function(val) {
var bizRequest = $http.post('/sample', {
  // var bizRequest = $http.post('/biz', {
      orgName: val,
      limit: 5
    }
  ).success(function(response){
    console.log(response)
    //console.log('Biz response: ' + JSON.stringify(response))
    //console.log(response.data.fields.map(item))
    var bizArray = response.data.fields.map(function(item){
      return item.fields.orgName;
    });
    console.log(bizArray);
    return bizArray;
  });
  console.log("Biz Request /////// " + JSON.stringify(bizRequest))
  return bizRequest
};

Node API (app.js)

app.post('/sample', function(req, res){

var resp = {
"success": true,
"data": {
    "fields": [{
        "fields": {
            "scid": "1111",
            "orgName": "1111",
            "countryCode": "1",
            "countryName": "1",
            "cityName": "1",
            "addressLine": "1111"
        },
        "matchedRule": {
            "duplicateLevel": "POTENTIAL_MATCH",
            "id": "18",
            "rank": "1"
        }
    }, {
        "fields": {
            "scid": "2222",
            "orgName": "2222",
            "countryCode": "22",
            "countryName": "22",
            "cityName": "22",
            "addressLine": "2 22"
        },
        "matchedRule": {
            "duplicateLevel": "POTENTIAL_MATCH",
            "id": "18",
            "rank": "1"
        }
    }]
},
"errors": [],
"warnings": [],
"infoMessages": []
}

res.send(JSON.stringify(resp))
})

Solution

  • You have to return promise from getLocation method while dealing asynchronous typeahead. So don't use .success there which would break promise chain. Instead use .then which would help you to chain promise and you can return data from .then to pass it to typeahead

    $scope.getLocation = function(val) {
      var bizRequest = $http.post('/sample', {
      // var bizRequest = $http.post('/biz', {
          orgName: val,
          limit: 5
        }
      ).then(function(data){
        response = data.data; //<-- take data in response.
        console.log(response.data)
        //console.log('Biz response: ' + JSON.stringify(response))
        //console.log(response.data.fields.map(item))
        var bizArray = response.data.fields.map(function(item){
          return item.fields.orgName;
        });
        console.log(bizArray);
        return bizArray;
      });
      console.log("Biz Request /////// " + JSON.stringify(bizRequest))
      return bizRequest
    };