用于循环进度的AngularJS DOM更新

时间:2013-04-21 12:40:29

标签: dom for-loop angularjs

我有一些AJAX调用需要为数组中的每个条目运行,我试图提供一些关于循环通过数组的进度的视觉反馈,模型正在正确更新但我'我没有在视图中看到任何更新,试图在循环中调用$ digest对DOM没有影响。

我尝试在内循环中添加$ apply到函数但我仍然没有看到变化。

$scope.UploadEntry = function(item){
var oDBGet = new htmldb_Get(null, 
                            $v('pFlowId'), 
                            "APPLICATION_PROCESS=UploadTargetDates", 
                            $v('pFlowStepId'));

oDBGet.add('EX_TRD',$scope.Ext.TRDDate.val);
oDBGet.add('EX_MAX_TRD',$scope.Ext.MaxTRDDate.val);
oDBGet.add('EX_READ',Ext.ReadDownloadCheck);
oDBGet.get();
};

$scope.ShowUploadModal = true;
$scope.UploadDone = 0;
for(i in submissionList)
{
        $scope.UploadEntry(submissionList[i]);
        $scope.UploadDone += 1;
}
$scope.ShowUploadModal = false;

但是观点:

<div class="UploadModal" ng-show="ShowUploadModal">
Uploading entries: {{UploadDone}} complete
</div>

从未看到条目已上传,但如果我从循环结束时取出$scope.ShowUploadModal = false;,则会在循环结束时显示。

1 个答案:

答案 0 :(得分:1)

<强>更新

经过讨论,作者声明http请求是同步的。问题仍然是“同步”,但有点小问题。看看Angular digest concepts。它基本上运行所有观察者,表达式(绑定)并一遍又一遍地处理所有$evalAsync,直到手表结果和表达式不再发生变化。在此之后,DOM被更新。

因此,问题是所有的同步请求都在摘要周期结束之前得到解决,而DOM呈现只会在摘要周期结束处理后才会发生。

解决问题的最简单方法,就是说你无法更改API来调用异步,就是确保你的请求是异步的,抓住他们的承诺,只有当所有这些都隐藏了uploadModal时已经完成(这可以通过promises API实现,阅读promises API$timeout)。像这样:

var loadingPromises = [];

$scope.ShowUploadModal = true;
$scope.UploadDone = 0;

for(i in submissionList) {
  loadingPromises.push($timeout((function(index) {
    return function() {
      $scope.UploadEntry(submissionList[index]);
      $scope.UploadDone += 1;
    };
  })(i), 0));
}

$q.all(loadingPromises).then(function() {
  $scope.ShowUPloadMOdel = false;
});

请注意我创建的闭包,以确保将正确的索引传递给请求,并且您需要向控制器注入$q服务。虽然这将解决您的问题,您应该创建一个服务并在那里移动您的加载逻辑,返回一个promise(将$ scope引用更改为参数):

app.service('yourLoaderService', function($timeout) {
  this.load = function(url) {
    return $timeout(function() {
      var oDBGet = new htmldb_Get(null, 
                        $v('pFlowId'), 
                        "APPLICATION_PROCESS=UploadTargetDates", 
                        $v('pFlowStepId'));

      oDBGet.add('EX_TRD',$scope.Ext.TRDDate.val);
      oDBGet.add('EX_MAX_TRD',$scope.Ext.MaxTRDDate.val);
      oDBGet.add('EX_READ',Ext.ReadDownloadCheck);
      oDBGet.get();
    }, 0);
  };
});

你的控制器:

var loadingPromises = [];

$scope.ShowUploadModal = true;
$scope.UploadDone = 0;

for(i in submissionList) {
  var promise = yourLoaderService.load(submissionList[i]).then(function() {
    $scope.UploadDone++;
  });

  loadingPromises.push(promise);
}

$q.all(loadingPromises).then(function() {
  $scope.ShowUPloadMOdel = false;
});

第一个回答

这是一个概念错误。你似乎来自同步服务器端的背景,也许是Python,我不知道。如果这是您的真实代码,那么问题是您的代码是完全同步的。您正在显示上传模型,循环所有条目并隐藏模型,整个代码在DOM渲染甚至一次之前都以毫秒(或更少)的速度发生。

这是因为当您要求上传时,Javascript不会挂起上传过程,它只是要求并继续。您可以找到有关异步编程herehereherehere的内容。

您必须在上传回调中连接上传的计数。我不知道您上传了什么,但是$scope.uploadEntry将返回promise,然后等待它完成并更新计数。

$scope.ShowUploadModal = true;
$scope.UploadDone = 0;
for(i in submissionList)
{
  $scope.UploadEntry(submissionList[i]).then(function() {
    $scope.UploadDone += 1;
    scope.ShowUploadModal = $scope.UploadDone !== submissionList.length;      
  });
}

如果您使用$http作为uypload作业,只需返回它,因为它已经是一个承诺并且每.then(funciton更改.success(function。如果没有,这将会更加复杂,您需要阅读Angular docs on promises

只是旁注,你应该看看Javascript命名对话。 Javascript通常假设cammelCase个变量,而不是PascalCase。这是David Crackford's convetion