Why is the binding to AngularJS not always updated correctly?

I am creating a simple image upload page that works with AWS S3 using the Danial Farid ng-file-upload plugin . It has a simple button to upload a new image and image list. Like this:

<ul> <li ng-repeat="image in product.images"> <a class="thumbnail" href="{{ image }}" target="_blank"> <img ng-src="{{ image }}" alt="image"> </a> </li> <li> <div class="btn-image-upload" ngf-select ngf-change="upload($files)" ngf-accept="'image/*'"></div> </li> </ul> 

On my controller:

 $scope.upload = function (files) { var aws_policy, aws_policy_signature; if (files && files.length) { $http .get(API_URL+'/helper/aws_policy') .then(function(data) { aws_policy = data.data.policy; aws_policy_signature = data.data.signature; for (var i = 0; i < files.length; i++) { var file = files[i]; var key = generate_aws_key() + '.' + file.name.split('.').pop(); var base_url = 'https://.../'; Upload .upload({ ... }) .success(function( data, status, headers, config ) { console.log($scope.product); $scope.product.images.push( base_url + key ); console.log($scope.product); }); } }); } }; 

The file loads properly (I get a good 204 Success from AWS), and two console.log($scope.product) receive called calls showing the corresponding results (the second is an element in the images array).

Here is the thing. This child works fine on my development machine, but sometimes on intermediate or production servers the list of images is not updated when $scope.product.images . Sometimes I mean that he does it 1/3 times.

Mixing

Sometimes, only on my production server, the DOM is not updated when $scope.product.images updated inside the AngularJS digest.

My programming experience taught me that sometimes this is not an acceptable concept in this type of question, and that this should be due to what always happens when this problem arises, but I debugged widely and did not find a real reason. Ideas?

+4
source share
1 answer

This is likely caused by a loop in asynchronous callbacks :

You must freeze the i value:

 $scope.upload = function (files) { var aws_policy, aws_policy_signature; function upload(index) { var file = files[index]; var key = generate_aws_key() + '.' + file.name.split('.').pop(); var base_url = 'https://.../'; Upload .upload({ ... }) .success(function( data, status, headers, config ) { console.log($scope.product); $scope.product.images.push( base_url + key ); console.log($scope.product); }); } if (files && files.length) { $http .get(API_URL+'/helper/aws_policy') .then(function(data) { aws_policy = data.data.policy; aws_policy_signature = data.data.signature; for (var i = 0; i < files.length; i++) { var file = files[i]; upload(i); } }); } }; 
+2
source

All Articles