angularjstypeahead.jsbootstrap-typeaheadangular-ui-typeahead

Typeahead is not working when user types very fast


I am using typeahead where on typing its showing suggestions in a search box, while suggestions are getting from the server.

Its working fine except when user types really fast. For example if we type storm it's showing records. When type same word with speed, it's not showing its suggestions while I am getting data in response. I have checked by printing JSON just above the box so when I write storm fastly its showing JSON but not showing below suggestions.

Here is the html

<input type="text" ng-model="header.search"
    typeahead-on-select="searchClicked($item)"
    uib-typeahead="state as state.data.name for state in suggestions | filter:$viewValue | limitTo:8"
    typeahead-min-length="0" placeholder="Søg..." search-products>

search-products is the directive use to broadcast search values. Here is the directive code.

APP.directive('searchProducts', searchProducts);
function searchProducts($state) {
    return {
        restrict: 'A',
        link: function(scope, element, attrs) {
            scope.$watch(attrs.ngModel, function(searchVal) {
                scope.$broadcast('searchTheProducts', searchVal);
            });
        }
    };
}

Here is the service call where we are getting data.

$scope.$on('searchTheProducts', function(event, query) {
    if (query) {
        headerService.getSearchSuggestions(query).then(
            function(response) {
                $scope.suggestions = response;
            },
            function(err) {
                console.log('Error: ' + err);
            }
        );
    }
});

here is the service logic

  function getSearchSuggestions(query) {
    pendingRequests.cancelAll();
    var url = ApiBaseUrl + "/search/suggestions?query=" + query;
    var deferred = $q.defer();
    pendingRequests.add({
        url: url,
        canceller: deferred
    });

    pending = true;
    $http({
        method: "GET",
        url: url,
        timeout: deferred.promise
    }).then(
        function(successData) {

            deferred.resolve(successData.data.data);
        },
        function(err) {

            deferred.reject(err);
        }
    );
    return deferred.promise;
}

Solution

  • I don't think you need a custom directive to fire the $http call to fetch the results whenever your input value changes.Instead you can do as below

    <input type="text" ng-model="header.search"
        typeahead-on-select="searchClicked($item)"
        uib-typeahead="state as state.data.name for state in suggestions($viewValue) | filter:$viewValue | limitTo:8"
        typeahead-min-length="0" placeholder="Søg..." >
    

    In your JS controller you can write the function $scope.suggestions() to fetch the new results on query type.

    var app = angular.module('plunker', ['ui.bootstrap']);
    
        app.factory('dataProviderService', ['$http', function($http) {
            var factory = {};
            factory.getCities = function(input) {
                //I've used google api to fetch cities ..we can place our service call here..
              return  $http.get('//maps.googleapis.com/maps/api/geocode/json', {
                    params: {
                        address: input,
                        sensor: false
                    }
                }).then(function(response) {//on success the results can be further processed as required..
                    return response.data.results.map(function(item) {
                        return item.formatted_address;
                    });
                });
    
            };
    
            return factory;
        }]);
    
         app.controller('TypeaheadCtrl', ['$scope', '$log','$http', 'dataProviderService', function($scope, $log,$http, dataProviderService) {
                $scope.suggestions= function(viewValue) {
                    //you can call your own service call via a factory 
                 return   dataProviderService.getCities(viewValue);
    
                };
    
            }]);
    

    Here is the DEMO of the working sample for the above mentioned way,hope this helps you.In this approach no mater how fast you type you will always fetch fresh results instantly.