Angular bootstrap typeahead with asynchronous load is one character behind
Asked Answered
H

2

7

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?

Hawfinch answered 16/11, 2015 at 19:17 Comment(1)
use $viewValue for searchFauch
G
4

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;
  });
};
Grano answered 23/11, 2015 at 21:17 Comment(0)
P
0

Typeahead must be faster than the page digest and therefore using scope instead of value its just not quite there.

Here is a plunker showing both versions. Essentially you need the first version as below

 scope.companyByName = function(val) {
    var companyName = val;
    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;
    });
  };
Persuasion answered 27/11, 2015 at 18:1 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.