Angularjs angular-ui-select2和breezejs:输入2个字符后加载ajax列表

Angularjs angular-ui-select2和breezejs:输入2个字符后加载ajax列表,angularjs,breeze,angularjs-select2,Angularjs,Breeze,Angularjs Select2,我有一个项目,我正在使用BreezeJS从我的Web服务器获取数据。我将AngularJS与ui-select2模块一起使用。目前,当我加载页面时,breezejs调用获取我转储到范围变量中的数据。从那里,select2可以轻松地对其进行引用并相应地构建 如果我想让事情变得有趣,那真的很棘手。我希望能够使用select2的ajax或查询支持,但我不想使用它来获取数据,而是想使用breezejs来实现。因此,在页面加载过程中,在进行ajax获取之前,在我开始输入最少X个字符之前,不会加载任何内容

我有一个项目,我正在使用BreezeJS从我的Web服务器获取数据。我将AngularJS与ui-select2模块一起使用。目前,当我加载页面时,breezejs调用获取我转储到范围变量中的数据。从那里,select2可以轻松地对其进行引用并相应地构建

如果我想让事情变得有趣,那真的很棘手。我希望能够使用select2的ajax或查询支持,但我不想使用它来获取数据,而是想使用breezejs来实现。因此,在页面加载过程中,在进行ajax获取之前,在我开始输入最少X个字符之前,不会加载任何内容

限制条件: 我不想使用select2的“ajax”获取数据。我想让BreezeJS来处理服务电话。当我使用ajax时,每当我按下一个字符以过滤结果(类似于自动完成),它都会发出ajax调用。我只希望列表加载一次,然后使用本机过滤

以下是我到目前为止的情况:

breezejs-StateContext.JS

m.app.factory('StateContext', ['$http', function ($http) {
    configureBreeze();

    var dataService = new breeze.DataService({
        serviceName: "/Map/api",
        hasServerMetadata: false
    });

    var manager = new breeze.EntityManager({ dataService: dataService});

    var datacontext = {
        getAllStates: getAllStates
    };
    return datacontext;


    function getAllStates() {
        var query = breeze.EntityQuery
                .from("States");
        return manager.executeQuery(query);
    }


    function configureBreeze() {
        breeze.config.initializeAdapterInstances({ dataService: "webApi" });
    }
}]);
这可以正常工作并正确返回json对象

以下是我如何称呼该服务:

m.app.controller('LocationCtrl', ['$scope', 'StateContext', function ($scope, StateContext) {

    $scope.getAllStates = function () {
        StateContext.getAllStates().then(stateQuerySucceeded).fail(queryFailed);
    }
    $scope.getAllStates();


    $scope.states = [];
    function stateQuerySucceeded(data) {
        data.results.forEach(function (item) {
            $scope.states.push(item);
        });
        $scope.$apply();

        console.log("Fetched States");
    }

    function queryFailed(error) {
        console.log("Query failed");
    }

    $scope.select2StateOptions = {
        placeholder: "Choose a State",
        allowClear: true,
        minimumInputLength: 2
    };
}
这是我的html:

<div ng-app="m" id="ng-app">
    ...
    ...

    <select ui-select2="select2StateOptions" ng-model="LocationModel.State">
        <option value=""></option>
        <option ng-repeat="state in states" value="{{state.id}}">{{state.name}}</option>
    </select>
</div>
问题出在这里。BreezeJS使用一个Q库,它使用一种叫做“承诺”的东西;这是一个承诺,即在进行ajax调用后将返回数据。问题在于,查询函数期望填充数据,但从查询函数返回后,承诺调用“stateQuerySucceed”函数

因此,它首先命中查询函数。然后点击getAllState()。从查询返回(不填充任何内容),然后调用“stateQuerySucceeded”

换句话说,即使我已经能够获取数据,但这已经太晚了。。select2的查询功能没有在正确的时间接收到数据,我的html select正在使用搜索微调器.gif挂起“搜索…”。

我真的不知道这一点。我认为文档的相关部分是以下示例:

$("#e5").select2({
    minimumInputLength: 2,
    query: function (query) {
       var data = {results: []}, i, j, s;
        // simulate getting data from the server
        for (i = 1; i < 5; i++) {
            s = "";
            for (j = 0; j < i; j++) {s = s + query.term;}
            data.results.push({id: query.term + i, text: s});
        }
        query.callback(data);
    }
});

正如我所说,我只是根据文档的快速阅读进行猜测。把这个答案当作一个“提示”,请不要指望我能坚持到底,让它真正起作用。谢谢你注意我的问题,我喜欢你的很多回答。这肯定是一个很好的响应,Select2UI是select2下拉列表的angularjs包装器。我使用您的代码取得了进展,但我想知道是否可以在使用服务器端数据加载一次之间切换,然后填充本地浏览器缓存,然后改用它?我很快就要解决这个问题了。比如让数据填充到浏览器缓存中,让breezejs查询并过滤这些数据?如果您注意到在我的代码getAllState()中,这个函数没有where子句。所以它不会模拟自动完成,每次我按下一个按钮,我都希望breezejs过滤结果。这就是我想使用缓存的原因,因为我不想每次按下按钮时都调用服务器来过滤结果(如果使用ajax,select2就是这样做的,但是如果在页面加载中使用本地数据,那么它会过滤本地传递的任何数据)。找到答案并阅读breeze文档。我将很快发布我的最终解决方案。很高兴你取得了进步。您完全可以调整Breeze是响应远程数据还是缓存数据。。。我想你已经学会了。期待你的发现。
$scope.select2StateOptions = {
    placeholder: "Choose a State",
    allowClear: true,
    minimumInputLength: 2,
    query: function (query) {
        debugger;
        var data = StateContext.getAllStates().then(stateQuerySucceeded).fail(queryFailed);
    }
};
$("#e5").select2({
    minimumInputLength: 2,
    query: function (query) {
       var data = {results: []}, i, j, s;
        // simulate getting data from the server
        for (i = 1; i < 5; i++) {
            s = "";
            for (j = 0; j < i; j++) {s = s + query.term;}
            data.results.push({id: query.term + i, text: s});
        }
        query.callback(data);
    }
});
$scope.select2StateOptions = {
    placeholder: "Choose a State",
    allowClear: true,
    minimumInputLength: 2,
    query: function (query) {
        StateContext.getAllStates()
                    .then(querySucceeded).catch(queryFailed);

       function querySucceeded(response) {
            // give the {results:data-array} to the query callback
            query.callback(response);
       }

       function queryFailed(error) {
           // I don't know what you're supposed to do.
           // maybe return nothing in the query callback?
           // Tell the user SOMETHING and then
           query.callback({results:[]});      
       }
    }
};