admin管理员组文章数量:1431426
I've got a weird one (for me at least) that hopefully someone will be able to help with. Maybe I'm just thinking about this the wrong way or something. Attempting to work with files in javascript is pletely new to me.
I've got a directive whose template looks like this:
<input type="file" ng-file-select ng-model="files">
<button ng-click="onFileSelect()">Upload</button>
In the controller for the directive, I am doing this:
$scope.onFileSelect = function() {
reader = new FileReader();
reader.onload = function() {
$scope.file_contents = this.result;
};
reader.readAsArrayBuffer($scope.files[0]);
//debugger;
$scope.$watch('file_contents',function(file_contents) {
console.log(file_contents);
if (angular.isDefined(file_contents)) {
... bunch of code attempting to deal with file_contents ...
}
});
};
I choose a file, then click the Upload button. The console.log of (file_contents) is undefined. Only when I click the button the second time, does it have a value.
If I unment the debugger, $scope.file_contents has a value by the time I'm checking it.
So, file_contents takes a moment to get set (which is expected), but the $watch never seems to notice? Is there some strange reason for this? Does $watch not work with FileReader objects?
Edit 1:
Okay. Here's some more information. Following PSL's advice, I now have the code as such:
$scope.onFileSelect = function() {
reader = new FileReader();
reader.onload = function() {
file_contents = this.result;
upload_file($scope.files[0],file_contents);
};
reader.readAsArrayBuffer($scope.files[0]);
};
upload_file = function(file,file_contents) {
<lots of cool file_contents-y stuff>
};
Why am I still getting $digest errors? I have no $watches any more. I don't do anything with $scope within upload_file. There's no stack trace from the $digest error to help me, either. All I get is:
Error: [$rootScope:inprog] $digest already in progress
.3.0-beta.10/$rootScope/inprog?p0=%24digest
What's doing this?
I've got a weird one (for me at least) that hopefully someone will be able to help with. Maybe I'm just thinking about this the wrong way or something. Attempting to work with files in javascript is pletely new to me.
I've got a directive whose template looks like this:
<input type="file" ng-file-select ng-model="files">
<button ng-click="onFileSelect()">Upload</button>
In the controller for the directive, I am doing this:
$scope.onFileSelect = function() {
reader = new FileReader();
reader.onload = function() {
$scope.file_contents = this.result;
};
reader.readAsArrayBuffer($scope.files[0]);
//debugger;
$scope.$watch('file_contents',function(file_contents) {
console.log(file_contents);
if (angular.isDefined(file_contents)) {
... bunch of code attempting to deal with file_contents ...
}
});
};
I choose a file, then click the Upload button. The console.log of (file_contents) is undefined. Only when I click the button the second time, does it have a value.
If I unment the debugger, $scope.file_contents has a value by the time I'm checking it.
So, file_contents takes a moment to get set (which is expected), but the $watch never seems to notice? Is there some strange reason for this? Does $watch not work with FileReader objects?
Edit 1:
Okay. Here's some more information. Following PSL's advice, I now have the code as such:
$scope.onFileSelect = function() {
reader = new FileReader();
reader.onload = function() {
file_contents = this.result;
upload_file($scope.files[0],file_contents);
};
reader.readAsArrayBuffer($scope.files[0]);
};
upload_file = function(file,file_contents) {
<lots of cool file_contents-y stuff>
};
Why am I still getting $digest errors? I have no $watches any more. I don't do anything with $scope within upload_file. There's no stack trace from the $digest error to help me, either. All I get is:
Error: [$rootScope:inprog] $digest already in progress
http://errors.angularjs/1.3.0-beta.10/$rootScope/inprog?p0=%24digest
What's doing this?
Share Improve this question edited Jan 26, 2015 at 3:35 Jim MacKenzie asked Jan 26, 2015 at 0:58 Jim MacKenzieJim MacKenzie 2224 silver badges16 bronze badges 02 Answers
Reset to default 7Watch never seems to notice because you are updating the scope outside of angular context. You would need to manually invoke digest cycle using scope.$apply()
or any other way like using a $timeout etc inside onload
async function. and better move the watch outside of the onFileSelect method otherwise you will keep on adding up watched every upload click.
Try:
$scope.onFileSelect = function() {
reader = new FileReader();
reader.onload = function() {
$scope.file_contents = this.result;
$scope.$apply(); /<-- here
};
reader.readAsArrayBuffer($scope.files[0]);
};
$scope.$watch('file_contents',function(file_contents) {
console.log(file_contents);
if (angular.isDefined(file_contents)) {
... bunch of code attempting to deal with file_contents ...
}
});
Not sure about the plete scenario but you probabaly don't even need to create a watch just wrap the file processing inside a method and invoke the method from onload
and perform a scope.$apply(). Reason why your watch executes for the first time is because it always runs once it is set up inorder to kick off dirty check and by that time async onload has not set any value on the scope and even if it does set up digest cycle is not aware of it.
There is a much nicer approach to this.. You define a directive like this..
//directive.js
(function() {
angular.module('<yourApp>').
directive('fileread', ['$parse', function($parse){
// Runs during pile
return {
restrict: 'A',
link: function($scope, iElm, iAttrs, controller) {
var model = $parse(iAttrs.fileread);
var modelSetter = model.assign;
iElm.bind('change', function(){
$scope.$apply(function(){
modelSetter($scope, iElm[0].files[0]);
});
});
}
};
}]);
})();
Then in your controller(or some other directive) you create a model like this..
//controller.js
...
$scope.photo.data = null;
...
$scope.photo.upload = function() {
fd = new FormData();
fd.append('<name_of_form_field_the_photo_should_be_sent_as>', $scope.photo.data);
$http.post('<url>', fd, {
transformRequest: angular.identity,
headers: {'Content-Type': undefined}
})
and finally in you html.
<input type = 'file' fileread = "photo.data">
<button ng-click = "photo.upload"> </button>
I hope it helps.
本文标签: javascriptAngularJS Problems with FileReader and scopewatchStack Overflow
版权声明:本文标题:javascript - AngularJS Problems with FileReader and $scope.$watch? - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1745575432a2664300.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论