0

Given this controller:

 angular.module("upload.app").controller("upload",[upload]);

 function upload(){
    var me = this;

     me.uploadList = [{Name: "Test Upload",
                       Id: 1,
                       NewFiles: []
                     }];
     me.selectedUpload = me.uploadList[0];
     me.setSelected = function(upload) {
        me.selectedUpload = upload;
     }
     ...
     me.addFilesToUpload = function(element){
        me.selectedUpload.NewFiles = element.files;
     }

and this html:

   <div ng-controller="upload as vm">
       <input id="filechooser" type="file" multiple onchange="angular.element(this).scope().vm.addFilesToUpload(this)" />
       <table>
          <tbody>
             <tr ng-repeat="up in vm.uploadList" ng-click="vm.setSelected(up)">
                 <td>{{up.Name}}<br />{{up.NewFiles.length}}</td>
             </tr>
          </tbody>
       </table>

       <table>
           <tbody>
              <tr ng-repeat="file in vm.selectedUpload.NewFiles">
                 <td>{{file.name}}</td>
              </tr>
           </tbody>
       </table>
   </div>  

I would expect that when the input onchange event calls addFilesToUpload() and the files are then added to the NewFiles property, that Angularjs would automatically update the view ... in this case, {{up.NewFiles.length}} value in the first table and the second table that lists the files.

However, nothing is being updated until I click on my row in the first table which, as you can see, fires the setSelected function on my controller.

How can I get Angular to refresh when the NewFiles property is changed as well?

Sorry, just fixed the fiddle -- forgot to save it originally See this jsfiddle. Begin by clicking on the Test Upload. Now select files. Nothing happens. Click again on Test Upload and you'll see all the bindings refreshed.

RHarris
  • 10,641
  • 13
  • 59
  • 103

3 Answers3

0

There is no default binding provided by angular to input type=file https://github.com/angular/angular.js/issues/1375, so you'll probably need to create your own directive or you can use angular-file-upload library.

Check out this answer from stackoverflow.

Community
  • 1
  • 1
Alex Choroshin
  • 6,177
  • 2
  • 28
  • 36
  • I'm not actually binding to input type=file. The question is in regards to the other bindings on my table elements that are bound to properties on my controller. See my jsFiddle. – RHarris Mar 28 '14 at 21:21
  • yes, but onchange="angular.element(this).scope().vm.addFilesToUpload(this)" method has a binding to input type=file – Alex Choroshin Mar 28 '14 at 21:25
0

Use $apply (DEMO):

$scope.$apply(function() {
    $scope.selectedUpload.NewFiles = element.files;
});

This is usually done by angular but because you are using the native js event onchange you have to wrap it in an $apply callback yourself.

Marcel Gwerder
  • 8,353
  • 5
  • 35
  • 60
  • Thanks Marcel. BTW, if you look at the code I included in this post above, I used a different pattern than what I used in jsFiddle ... I don't inject scope. Is there a way to use apply without $scope or will I have to pass $scope in to my controller? – RHarris Mar 29 '14 at 03:46
  • `.controller('upload',['$scope', upload]);` and `function upload($scope){` should work for that one... – Marcel Gwerder Mar 29 '14 at 11:18
0

The problem with your updated fiddle is mainly this line

$scope.selectedUpload = null;

The moment you have selected the files and invoke the callback addFilesToUpload(), and assign the selected files to $scope.selectedUpload.NewFiles = element.files; then you'll definitely get an error:

Uncaught TypeError: Cannot set property 'NewFiles' of null

Simply change it back to your original code: $scope.selectedUpload = $scope.uploadList[0];

The next problem would be to update the current selected upload list, simply use $scope.$apply(), because you are using a native event onchange to update the $scope. Your callback should look this:

 $scope.addFilesToUpload = function(element){
     $scope.$apply(function() {
        $scope.selectedUpload.NewFiles = element.files;     
     });
 }

Check this updated fiddle.

ryeballar
  • 29,658
  • 10
  • 65
  • 74