选择列表的angularjs绑定/范围问题?

时间:2013-07-09 13:24:47

标签: angularjs angularjs-scope

确定将我的代码切换到angularjs和有角度的方式,不知道我做错了什么。

当模型发生变化时,选择列表不会更新,除非我调用$ apply,我发现自己调用了很多。

index.html有这个:

<div id='rightcol' data-ng-include="'partials/rightSidebar.html'"  
    data-ng-controller="rightSidebarController">
</div>

和rightSidebar.html有:

<select id='srcList' size='10'
        data-ng-model="data.source" 
        data-ng-click='srcOnclick()'
        data-ng-options="s.title for s in data.srcList | filter:{title:data.srcFilter} | orderBy:'title'"></select>

rightSidebarController.js有:

$scope.data = {};
$scope.data.srcList = dataProvider.getSourceList();
$scope.data.source = dataProvider.getSource();

dataProvider是一个服务,它使异步数据库调用(IndexedDB)填充srcList,这是在dataProvider.getSource()中返回的。

是异步数据库调用强制我调用$ apply,还是控制器应该不知道?

是否有更好的&#39;这样做的方法?

编辑添加服务代码。

另一个控制器调用dataProvider.refreshSourceList:

myDB.refreshSourceList = function() {
    myDB.getRecords("source", function(recs) {
        myDB.srcList = recs;
        $rootScope.$broadcast('SrcListRefresh');
    });
};

myDB.srcList是$ scope.data.srcList = dataProvider.getSourceList();

绑定的字段

myDB.getRecords:

myDB.getRecords = function(storeName, callback) {
    var db = myDB.db;
    var recList = [];
    var trans = db.transaction([storeName], 'readonly');
    var store = trans.objectStore(storeName);

    var cursorRequest = store.openCursor();
    cursorRequest.onerror = myDB.onerror;

    cursorRequest.onsuccess = function(e) {
        var cursor = cursorRequest.result || e.result;
        if (cursor === false || cursor === undefined) {
            if (callback !== undefined) {
                $rootScope.$apply(function() {
                    callback(recList);
                });
            }
        } else if (cursor.value !== null) {
            recList.push(cursor.value);
            cursor.continue();
        }
    };

    cursorRequest.onerror = myDB.onerror;
};

1 个答案:

答案 0 :(得分:1)

您执行异步操作的任何内容都需要包含在$scope.$apply()中。这是因为角度以类似于游戏循环的方式工作,但是它不是经常运行,而是知道在采取动作时结束循环,并且调用$scope.$digest()

如果您使用的是IndexedDB,我建议为它创建一个角度包装器,如下所示: (原谅我的IndexedDB代码,我没有经验)

angular.module('app',[])
    .factory('appdb', function($rootScope){
        var db = indexedDB.open('appdb', 3);
        return {
            get : function(table, query, callback) {
                var req = db.transaction([table])
                    .objectStore(table)
                    .get(query);

                req.onsuccess(function(){
                    $rootScope.$apply(function(){
                        callback(req.result);
                    });
                });
            }
        };
    });

通过这种方式,您可以确保在callback内的控制器范围内检索和设置的任何数据都会在之后调用$scope.$digest()