I have a img tag and an input file looking the like this:
<img ng-src="{{item.showImage || '//:0'}}" />
<input type="file" accept="image/*" onchange="angular.element(this).scope().getImage(this.files)"/>
on the controller I have the following function:
$scope.getImage = function(files){
$scope.item.image = files[0];
var reader = new FileReader();
reader.onload = function(e){
$scope.item.showImage = e.target.result;
}
reader.readAdDataURL($scope.item.image);
}
My purpose is to show the image selected by the user in the img tag using ng-src, this works only when I call $scope.$apply(), I wonder if there's a way to make it work without calling it?
Sara Fuerst
6,1389 gold badges49 silver badges95 bronze badges
asked Mar 29, 2015 at 12:03
Kadosh
3191 gold badge3 silver badges12 bronze badges
-
no, see this issue: github.com/angular/angular.js/issues/1375eladcon– eladcon2015年03月29日 12:13:32 +00:00Commented Mar 29, 2015 at 12:13
-
@squiroid this is not a duplicate as i know how to catch the chnages, just wondering how to make the new file selected show in the ng-srcKadosh– Kadosh2015年03月29日 12:20:20 +00:00Commented Mar 29, 2015 at 12:20
1 Answer 1
You can have a look at this plunker. You can use a directive for the image field that will watch for changes and will also return the image in a way that the template will be able to display it.
var UploadController = function ($scope, fileReader) {
$scope.getFile = function () {
fileReader.readAsDataUrl($scope.file, $scope)
.then(function(result) {
$scope.imageSrc = result;
});
};
};
app.directive("ngFileSelect",function(){
return {
link: function($scope,el){
el.bind("change", function(e){
$scope.file = (e.srcElement || e.target).files[0];
$scope.getFile();
})
}
}
});
Then you will also need that as a service:
(function (module) {
var fileReader = function ($q, $log) {
var onLoad = function(reader, deferred, scope) {
return function () {
scope.$apply(function () {
deferred.resolve(reader.result);
});
};
};
var getReader = function(deferred, scope) {
var reader = new FileReader();
reader.onerror = onError(reader, deferred, scope);
return reader;
};
var readAsDataURL = function (file, scope) {
var deferred = $q.defer();
var reader = getReader(deferred, scope);
reader.readAsDataURL(file);
return deferred.promise;
};
return {
readAsDataUrl: readAsDataURL
};
};
module.factory("fileReader",
["$q", "$log", fileReader]);
}(angular.module("plunker")));
answered Mar 29, 2015 at 12:28
manosim
3,69013 gold badges48 silver badges68 bronze badges
Sign up to request clarification or add additional context in comments.
1 Comment
Kadosh
That's a great solution but still uses $scope.$apply, i was looking for something that doesn't require me to do that.
lang-js