Reputation: 937
I am trying to write a file-reader directive using AngularJS that will take in images and then push their URL into an array so I can then iterate through that array and draw the images to the DOM.
However, I can't seem to get the needed URL out of the uploaded image in order to call it within an image source tag. Here is what I'm dealing with:
fileReader directive
app.directive('fileReader', ['$rootScope', function($rootScope) {
return {
restrict: 'E',
scope: true,
templateUrl:'views/templates/file-reader.html',
link: function (scope, element, attributes, controller) {
element.bind("change", function(event) {
var files = event.target.files;
var reader = new FileReader();
reader.onload = function() {
$rootScope.imageInfo = this.result;
$rootScope.$digest(); //digest is required to run with watch?
console.log("caught a change");
};
reader.readAsDataURL(files[0]);
});
},
controller: 'UploadController'
}
}]);
UploadController
controllers.controller('UploadController', ['$scope', '$rootScope', function($scope, $rootScope){
$scope.imageUrls = []; //array of URL
$rootScope.$watch('imageInfo', function() {
if ($rootScope.imageInfo) { //if something has been loaded
console.log("Inside the rootScope watch function");
$scope.imageUrls.push($rootScope.imageInfo); //add the URL to the array
}
$scope.printArray();//to check if the array worked
});
$scope.printArray = function(){
console.log("this is the image URL array:");
for(var i=0; i<$scope.imageUrls.length; i++){
console.log($scope.imageUrls[i]);
};
console.log("end image url");
};
}]);
file-reader.html: <input type='file' id="files" name="files[]">
And so originally, I had my reader.readAsDataURL(file[0])
line outside of the onload block, but it wasn't passing a URL I had pulled via the reader.
However this way the $watch isn't even being activated. Why not?
How can I use this to help pass the URLs of the images from the upload into an array?
(This is all client-side. I realize I'm not actually "uploading" anything beyond the DOM.)
Update:
I've fixed the problem of $watch not being called by simply calling a $digest, but I still can't manage to grab the URLs of the data to create an image as opposed to something like: data:image/gif;base64,R0lGODlh9QC0AOZ0AAwKClNNSpeWloeGhvTXozAqKbe2t0osEMm4r…1pGcsCIoJgiyf8+HPbIGY+OCEjIGhIBw8g8GDcnHgVKnCVCm7BAIooctEhiymDoBHBF4EAADs=
I rearranged a few of the terms and have updated the code above within the directive.
Upvotes: 0
Views: 557
Reputation: 716
Have you tried setting objectEquality to true in your $watch function like so:
$rootScope.$watch('imageInfo', function() {
if ($rootScope.imageInfo) { //if something has been loaded
console.log("Inside the rootScope watch function");
$scope.imageUrls.push($rootScope.imageInfo); //add the URL to the array
}
$scope.printArray();//to check if the array worked
}, true); // add true here
This listens for changes in nested values as well
Also here is a a little article/blog post I found giving a good breakdown and performance of the different $watch mechanisms. May come in handy when deciding which $watch function to use:
http://teropa.info/blog/2014/01/26/the-three-watch-depths-of-angularjs.html
Upvotes: 1