ui.bootstrap.typeahead: how to combine $http with debounce

我怕爱的太早我们不能终老 提交于 2019-12-07 13:40:20

问题


I'd like to take advantage of ui.bootstrap.typeahead because it is excellent. I'm implementing a search of a database that could contain millions of users, so I would really like to be able to debounce keystrokes in the search box before making a call to $http. Otherwise every keystroke will result in a search, and early keystrokes will generate slower searches than later keystrokes, resulting in a clunky user experience.

My current effort, which doesn't work, looks like this:

JavaScript:

angular.module("mycontrollers").controller("myCtrl", [
    "$scope", "$http", "rx", "localisationService", "close", function ($scope, $http, rx, localisationService, close) {
        var culture = localisationService.getCulture();
        function getUsersObservable(val) {
            return rx.Observable
                .fromPromise($http.get("/api/" + culture + "/usersearch", { params: { userName: val } }))
                .map(function (response) {
                    return response.data;
                });
        }
        $scope.close = close;
        $scope.$createObservableFunction("getUsers")
            .debounce(400)
            .filter(function (val) {
                return val.length > 0;
            })
            .flatMapLatest(getUsersObservable)
            .subscribe();
    }
]);

HTML:

<div class="form-group">
    <label for="the-user" localised-text-key="TheUser"></label>
    <input type="text" id="the-user" ng-model="userId" uib-typeahead="user for user in getUsers($viewValue)" typeahead-loading="loadingUsers" class="form-control" />
</div>

Server Side:

public async Task<IHttpActionResult> Get(string userName)
{
    var users = await _modelContext.Users.Where(u => u.UserName.Contains(userName)).OrderBy(u => u.UserName).Select(u => u.UserName).Take(20).ToArrayAsync();
    return Ok(users);
}

The input is being debounced correctly; the rx.observable at the start of the JavaScript is returning the search results as an array of strings, and debouncing the input correctly. What I'm not sure how to do is to package the results up into a promise that can be interpreted correctly by ui.bootstrap.typeahead.


回答1:


Ok, I totally missed it in the docs

ng-model-options $ - Options for ng-model (see ng-model-options directive). Currently supports the debounce and getterSetter options.

So the directive allows you to attach options to it's ng-model very much as plain ol' Angular does.

So you can then use it to set a debouce to your model value, and then call a function through the ng-change directive.

<input type="text" id="the-user" 
    ng-model="userId" 
    ng-model-options="{'debounce': 500}" 
    ng-change="sendHttpAfterDebounce()"
    uib-typeahead="user for user in getUsers($viewValue)" typeahead- 
    loading="loadingUsers" 
    class="form-control" />

Now your function (sendHttpAfterDebounce) will run 500 milliseconds after you're done typing.



来源:https://stackoverflow.com/questions/40126717/ui-bootstrap-typeahead-how-to-combine-http-with-debounce

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!