Ng-repeat does not handle FileReader

So this is how my view looks like:

<body ng-controller="AdminCtrl">
<img ng-repeat="pic in pics" ng-src="{{pic}}" />
<form ng-submit="postPic()">
    <input id="photos" type="file" accept="image/*" multiple/>
    <button>Add Pics</button>
</form>

      

And this is the controller:

app.controller('AdminCtrl',['$scope', function($scope){
    $scope.pics =[];

    $scope.postPic = function() {
        var files = $('#photos').get(0).files;

        for (var i = 0, numFiles = files.length; i < numFiles; i++) {
            var photoFile = files[i];
            var reader = new FileReader();
            reader.onloadend = function(e){
                $scope.pics.push(e.target.result);
                console.log($scope.pics);
            };
            reader.readAsDataURL(photoFile);
        }
    };

      

Although I select a lot of files and they are displayed in the console (albeit asynchronously), I cannot update the view based on update $scope.pics

. Is it observed $scope.pics

? Why is this happening?

+3


source to share


1 answer


The problem is that you are changing the $ scope object asynchronously, so angular doesn't know the changes that need to be handled. angular is not constantly looking at your $ scope object. The reason you usually don't need to explicitly use $scope.$apply()

is because angular will automatically do this for you most of the time if you are inside the angular ecosystem (i.e.: controller constructors, $ scope functions, etc.). ...

app.controller('AdminCtrl',['$scope', function($scope){
    $scope.pics =[];

    $scope.postPic = function() {
        var files = $('#photos').get(0).files;

    for (var i = 0, numFiles = files.length; i < numFiles; i++) {
        var photoFile = files[i];
        var reader = new FileReader();
        reader.onloadend = function(e){
            $scope.pics.push(e.target.result);
            console.log($scope.pics);
            $scope.$apply(); // force digest cycle
         };
         reader.readAsDataURL(photoFile);
    }
};

      



This is the same reason angular provides a service $timeout

that is only a wrapper for setTimeout

, but will automatically call the digest loop: fooobar.com/questions/82939 / ...

TL; DR; Asynchronous functionality [other than inline angular stuff] is outside the angular ecosystem, so you have to tell angular about $ scope changes via$scope.$apply()

+4


source







All Articles