user2465164
user2465164

Reputation: 937

Image upload and display on the DOM via Angular directive

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

Answers (1)

Daveloper87
Daveloper87

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

Related Questions