AngularJS ngRepeat 不正确地更新显示

4
我有一个页面,使用plupload上传文件,并且在ng-repeat中遇到了更新不正确的问题。以下是相关代码:
<div ng:app>
  <div name="myForm" ng-controller="Ctrl">
    <input ng-model="test" type="text" />{{test}}<div id="container" class="controls">
    <div id="filelist">
      <div ng-repeat="file in filesToUpload">{{file.name}} ({{file.size}}) <b>{{file.percent}}</b></div>
      </div>
      <br />
      <a id="pickfiles" href="#">[Select files]</a>
    </div>
  </div>
</div>​

function Ctrl($scope) {
    $scope.test = '';$scope.filesToUpload = [{id: 1, name: 'test', size: '123kb'}];

    $scope.addItem = function(object) {
        $scope.filesToUpload.push(object);
    }

    $scope.uploader = new plupload.Uploader({
        runtimes : 'html5,flash,browserplus,gears',
        browse_button : 'pickfiles',
        container : 'container',
        max_file_size : '10mb',
        url : 'upload.php',
        flash_swf_url : '/plupload/js/plupload.flash.swf'
    });

    $scope.uploader.init();

    $scope.uploader.bind('FilesAdded', function(up, files) {
        $scope.filesToUpload = [];
        $.each(files, function(i, file) {
            $scope.addItem({
                id: file.id,
                name: file.name,
                size: plupload.formatSize(file.size)
            });
        });

        console.log($scope.filesToUpload);

        up.refresh(); // Reposition Flash/Silverlight
    });
}​

这里是一个简化版的 jsfiddle,展示了问题的发生:

http://jsfiddle.net/9HuUC/

要重现此问题,请执行以下操作:

  1. 点击 [选择文件] 并选择一些文件(请注意,您不会在输出的任何地方看到文件显示)
  2. 在输入框中键入任何字符(神奇的是,您选择的文件现在出现了)

什么会导致这种类型的行为?我的意思是,我知道数据在 $scope.filesToUpload 中被正确设置,因为我在那里有 console.log(),甚至在 Batarang 中检查过,看起来很好,但由于某种原因,需要更新其他东西才能更新显示。

有趣的是,我在同一页上还有另一个正常工作的 ng-repeat。我想知道它是否与代码所在位置有关(位于 uploader 的 FilesAdded 事件内部)。


我认为在 ng-repeat 后面有一个额外的闭合 div 标签。 - qualidafial
1个回答

8
问题出在FilesAdded回调函数是由上传器外部执行的,因此它不在AngularJS的作用域内(它是由上传器调用的),所以作用域更新不会被触发。
为了解决这个问题,只需在回调函数中添加$scope.$apply调用,将现有代码封装起来即可:
$scope.uploader.bind('FilesAdded', function(up, files) {
    $scope.$apply( function() {
        $scope.filesToUpload = [];
        $.each(files, function(i, file) {
            $scope.addItem({
                id: file.id,
                name: file.name,
                size: plupload.formatSize(file.size)
            });
        });

        console.log($scope.filesToUpload);

        up.refresh(); // Reposition Flash/Silverlight
    });
});

通过此更新,它在 Fiddle 中可以正常工作。有关参考,请查看 AngularJS 官方文档$apply 方法的 scope 对象: http://docs.angularjs.org/api/ng.$rootScope.Scope


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接