Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular bootstrap typeahead with asynchronous load is one character behind

I have implemented the following typeahead code in a directive.

Here is the HTML:

<div>
    <input type="text"
           ng-model="company"
           uib-typeahead="company as company.name for company in companyByName($viewValue)"
           typeahead-loading="loadingCompanies"
           typeahead-no-results="noCompanyResults"
           class="form-control">
    <i ng-show="loadingCompanies" class="glyphicon glyphicon-refresh"></i>
    <div ng-show="noCompanyResults">
        <i class="glyphicon glyphicon-remove"></i> No Results Found
    </div>
</div>

Here is the JavaScript:

  scope.companyByName = function() {
    var companyName = scope.company.name ? scope.company.name : scope.company;
    var searchTerms = {name: companyName, startRow: 0, endRow: 20};

    return $http.post("backend/get/companies.php", searchTerms).then((result) => {
      $log.info("Companies", result.data.results);
      return result.data.results;
    });
  };

The PHP code backend/get/companies.php accepts a search string and returns an array of objects with id and name attributes with names that contain that search string.

Here is the behavior that I am experiencing:

When I type a single character "f" into the typeahead field, the value of companyName passed to the backend script is "" (empty string). backend/get/companies.php returns all results.

When I type a second character "fo" in the the typeahead field, the value of companyName passed to the backend script is "f". backend/get/companies.php returns results that match "f".

Typing a third character "foo" returns results that match "fo", etc.

I have modeled my code after the official examples. What is going on? My feeling is that somehow the companyByName() function is being called by an event that fires before the character is entered into the input. Any thoughts?

like image 650
jkndrkn Avatar asked Nov 16 '15 19:11

jkndrkn


1 Answers

Problem is that ng-model is lagging behind view values. When companyByName is called ng-model is not updated to latest value from input field. To get latest value from input you should use argument that is passed into companyByName function:

scope.companyByName = function(viewValue) {
  var searchTerms = {name: viewValue, startRow: 0, endRow: 20};

  return $http.post("backend/get/companies.php", searchTerms).then((result) => {
    $log.info("Companies", result.data.results);
    return result.data.results;
  });
};
like image 91
Stubb0rn Avatar answered Sep 30 '22 04:09

Stubb0rn