0
votes

I'm in this problem a days. What happens is the following when I try to click the update image button I can not do the image update on the first try despite my console.log it return me the correct value. What happens is that when I make the request to the backend the first time I load the update button it always returns the blob of the image that was previously and when I try again it returns the blob of the image that I tried to perform in the previous moment and Inserts into DB. In short he is always with a late request and I do not do the least because. I already tried to add the $ scope. $ Apply () and it did not work.

First update the blob of the previous image

Second update the blob correct of the image

In short I need to do update twice to be able to change the image to the one I want.

Code:

function uploadFile(){
    var file = $scope.profilePic;
    var blob = new Blob([file], {
        "type": "text/html"
    });

    var reader = new FileReader();

    reader.onload = function(e) {
        $scope.text = e.target.result.split(',')[1];
        $scope.loadedUser.profilePic = $scope.text;
    }

    reader.readAsDataURL(blob);

}; 

Html:

<div layout-gt-sm="row" style="margin-bottom: 20px;">                                                    
    <input type="file" name="profilePic" fileread="profilePic"> 
</div>

APP:

app.directive("fileread", [function () {
    return {
        scope: {
            fileread: "="
        },
        link: function (scope, element, attributes) {
            element.bind("change", function (changeEvent) {
                scope.$apply(function () {
                    scope.fileread = changeEvent.target.files[0];
                    // or all selected files:
                    // scope.fileread = changeEvent.target.files;
                });
            }); 
        } 
    }
}]);
1

1 Answers

0
votes

Part of the problem is that the directive uses two-way = binding with isolate scope. A digest cycle is necessary to transfer the data from the isolate scope to the parent scope.

One approach is to use expression & binding and expose the file as a local:

<div layout-gt-sm="row" style="margin-bottom: 20px;">
    <input type="file" name="profilePic" fileread="profilePic = $file">
</div>
app.directive("fileread", function () {
    return {
        scope: {
            //fileread: "="
            fileread: "&"
        },
        link: function (scope, element, attributes) {
            element.bind("change", function (changeEvent) {
                scope.$apply(function () {
                var file = changeEvent.target.files[0];
                scope.fileread({$file: file});
                scope.$apply()
            }); 
        } 
    }
});

In the above example, when a change event occurs, the directive evaluates the Angular expression defined by the fileread attribute with the file exposed as $file. The $file value is immediately available to the parent scope without the need of a watcher (and digest cycle) to transfer the value from isolate scope to parent scope.

Another problem is that reader.onload event occurs outside the AngularJS framework and needs a $scope.$apply() to process the changes to scope. For more information, see SO: FileReader onload only works the second time around in browsers.