0

好的,将我的代码切换到 angularjs 和 angular '方式',不确定我做错了什么。

除非我调用 $apply,否则当模型更改时,选择列表不会更新,而且我发现自己经常调用 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,还是控制器应该对此一无所知?

有一个更好的方法吗?

编辑添加服务代码。

另一个控制器调用 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;
};
4

1 回答 1

1

你做的任何异步操作都需要包含在$scope.$apply(). 这是因为 Angular 以类似于游戏循环的方式工作,但是它不会一直运行,而是知道在采取行动并被$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()之后调用。

于 2013-07-09T13:51:58.640 回答