如何让AngularJS在ng-repeat阵列拼接上更新DOM? $ scope。$ apply()返回错误

时间:2015-05-29 18:58:14

标签: javascript angularjs dom angularjs-ng-repeat

已解决 - 我有这个plunkr,它展示了我面临的问题。这是一个简单的图片上传器,它还使用FileReader来显示图片(感谢angular-file-uploads)。我把它放在一个动态的形式,可以添加和删除。

的问题:

  1. 在此plunkr中,dataUrl只有在点击Add Another Image后才会显示。从那以后,这可能是一个唯一的问题 图像在我的网站上很好地显示。 --SOLVED

  2. 如果您将图像上传到第一个表单,然后单击Add Another Image,然后单击第一个选项卡,然后删除第一个选项卡,数据将在$scope.images中删除但DOM没有更新。添加$scope.$apply()会导致摘要中的摘要错误。

  3. 旧文件名显示在上传输入中,但输入实际上是空的。

  4. 我的问题是:删除图像后如何更新DOM?

    更新:问题#1已解决,但问题#2和#3仍然存在。

    更新2:我已尝试为$scope.$apply附加<input type="file" onchange="...",但使用splice()删除图片并未触发onchange事件。

    Update3:我添加了一个带有ng-model="image.caption"的简单文本输入,以查看DOM是否会适当更新。确实如此。如果images[0]已删除images[1],则DOM也会正确更新。

    Update4: Grundy发现了问题:track by $index。删除它可以使一切按预期工作。虽然不太确定原因。

3 个答案:

答案 0 :(得分:3)

ngRepeat 中的跟踪表达式出现问题
正如ngRepeat

的文档所述
  

ngRepeat对DOM进行相应的更改:

     
      
  • 添加项目时,会将新模板实例添加到DOM中。
  •   
  • 删除项目后,将从DOM中删除其模板实例。
  •   
  • 重新排序项目时,各自的模板将在DOM中重新排序。
  •   

所以,在你拼接第一个元素的情况下, index 最后一个元素更改为 first 和angular认为只需从DOM中删除最后一个元素,而不需要先改变。

此外, $ index $ last 等是 ngRepeat 范围内的一个特殊属性,因此它始终可用而不依赖于< em>追踪 expresion

答案 1 :(得分:1)

由于您的指令处理AngularJs中摘要周期之外的事件,因此您需要在scope.$apply()中包含对范围的任何更新。所以在你的指令中:

 reader.onload = function() {
   var dataURL = reader.result;
   scope.$apply(function() {
     scope.$parent.upload(file, dataURL, attributes.angularFileUploads);
   });
 };

答案 2 :(得分:0)

似乎image.dataUrl是缓存的东西。

添加

ng-if="image.dataUrl"

<img>代码

似乎可以解决这种情况,但它并没有解决潜在的问题......不管它是什么。