Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AngularJS ngRepeat Not Updating Display Properly

I have have a page where I am using plupload to upload files and having a weird issue with a ng-repeat not updating properly. Here is the relevant code:

<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
    });
}​

Here is a trimmed down jsfiddle showing the issue happening:

http://jsfiddle.net/9HuUC/

To reproduce this issue do the following:

  1. Click on [select files] and selects a few files (notice how you don't see the files displayed anywhere on the output)
  2. Type any character into the input box (magically the files that you select know appear)

What would cause this type of behavior? I mean I know that the data is properly being set in $scope.filesToUpload because I have the console.log() there and even checked it in Batarang and it loods good there but for some reason something else needs to be updated for the display to be updated.

Interestingly enough, I have another ng-repeat that is working fine on the same page. I am wondering if it has anything to do with where the code is (being inside the FilesAdded event on the uploader).

like image 649
ryanzec Avatar asked Feb 19 '23 15:02

ryanzec


1 Answers

The issue is due to the fact that the FilesAdded callback is executed outside the scope of AngularJS (it's called by the uploader), therefore the scope updates won't be triggered.

To solve this, just add the $scope.$apply call in the callback, encapsulating your existing code:

$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
    });
});

With this update, it's working in the fiddle. For reference see the AngularJS official documentation, $apply method of the scope object: http://docs.angularjs.org/api/ng.$rootScope.Scope

like image 66
David Riccitelli Avatar answered Mar 12 '23 01:03

David Riccitelli