tarekahf tarekahf - 3 months ago 44
AngularJS Question

How to stop upload action for ng-flow plugin after drag and drop event

I am using simple drag and drop effect based on the simple image upload example provided with the download of ng-flow. the drag-and-drop is working fine, but I want to stop the default upload action since I want to upload the image using the form submit action or using Angular

.post()
function:



<html ng-app="app" ng-controller="imageController" flow-init
flow-file-added="!!{png:1,gif:1,jpg:1,jpeg:1}[$file.getExtension()]"
flow-files-submitted="$flow.upload()">
<head>
<title>Image</title>
<!-- <script src="../../bower_components/angular/angular.js"></script> -->
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
<script src="../../js/ng-flow-standalone.js"></script>
<script src="app.js"></script>
<link href="http://netdna.bootstrapcdn.com/twitter-bootstrap/2.3.2/css/bootstrap-combined.min.css"
rel="stylesheet"/>
<style>
.thumbnail {
max-width: 200px; max-height: 150px; line-height: 20px; margin-bottom: 5px;
}
</style>
</head>
<body flow-prevent-drop>

<div class="container" >
<h1>flow image example</h1>
<hr class="soften"/>

<div>
<div class="thumbnail" ng-hide="$flow.files.length"
flow-drop flow-drag-enter="style={border:'4px solid green'}" flow-drag-leave="style={}" ng-style="style">
<img src="http://www.placehold.it/200x150/EFEFEF/AAAAAA&text=no+image" />
</div>
<div class="thumbnail" ng-show="$flow.files.length">
<img flow-img="$flow.files[0]" />
</div>
<div>
<a href="#" class="btn" ng-hide="$flow.files.length" flow-btn flow-attrs="{accept:'image/*'}">Select image</a>
<a href="#" class="btn" ng-show="$flow.files.length" flow-btn flow-attrs="{accept:'image/*'}">Change</a>
<a href="#" class="btn btn-danger" ng-show="$flow.files.length"
ng-click="$flow.cancel()">
Remove
</a>
</div>
<p>
Only PNG,GIF,JPG files allowed.
</p>
</div>
</div>
</body>
</html>





I tried to use event.preventDefault(); in "fileAdded" and "filesSubmitted" events handlers, but this is not stopping the upload start event. I want to execute the upload process during the form submit process.

When I use "return false" in "fileAdded" event, the image won't be inserted at all.

However, if I inject an error in the "filesSubmitted" event handler, the script will fail, and the upload won't be triggered. But this is not a clean way for achieving this effect.

I also used this code but it is preventing the image from being added to the page:

app.controller('imageController',
['$scope',
function ($scope) {
$scope.$on('flow::fileAdded', function (event, $flow, flowFile) {
console.log('$scope.$on', event, $flow);
event.preventDefault();//prevent file from uploading
console.log("event.preventDefault() executed.")
});
}])


See snapshots below for more details.

Appreciate your help to resolve this issue.

enter image description here
enter image description here

Answer

I figured out what is needed to stop triggering the upload action so that we can submit the image data during Angular post() instead of form submit action.

Either remove the configuration property target from:

.config(['flowFactoryProvider', function (flowFactoryProvider) {
    flowFactoryProvider.defaults = {
        target: 'upload.php',
        permanentErrors: [404, 500, 501],
        maxChunkRetries: 1,
        chunkRetryInterval: 5000,
        simultaneousUploads: 4,
        singleFile: true,
};

or invoke the .pause() method from one of the events:

$scope.$on('flow::fileAdded', function (event, $flow, flowFile) {
    console.log('flow::fileAdded - appraiser signature', event, $flow, flowFile);
    ...
    $scope.processFile(flowFile);
    flowFile.pause();
    ...
});

Or form this event inside the .config() function:

  flowFactoryProvider.on('fileAdded', function(file, event){
      console.log('fileAdded', file, event);
      file.pause();
      event.preventDefault();
      console.log('file upload was paused.');
      return true;
  });

And, in order to retrieve the Base64 string of the selected image, you need to define the following function inside the controller:

    $scope.processFile = function(flowFile){
        console.log('$scope.processFile', flowFile);
        var fileReader = new FileReader();
        fileReader.onload = function (event) {
                console.log('fileReader.onload - event=', event);
                var uri = event.target.result;
                $scope.imageString = uri;
                $scope.imageStringB64 = uri.replace(/^data:image\/(png|jpg);base64,/, '');
        };
        fileReader.readAsDataURL(flowFile.file);
    };      

With the above, you have retrieved the Base64 value of the image in the scope variable imageStringB64 which you can then send to the server using $http.post() function instead of using the traditional form submit button.

I hope you will find the above useful.

Tarek