Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Disable button while server processing in AngularJS

I'm having problems disabling a button while processing a "long" request on the server.

Our application runs on a Java Spring/Tomcat backend and the front is using AngularJS. Our users can click on a "Export" button to get a CSV file of some statistics. The problem is that this file is generated server-side by calling a URL like this:

<a ng-href="/exports?id={{the_id}}>Export</a>

and the response type is: application/octet-stream.

The request works fine but can be a bit slow. I'd like to disable the button while the file is generating, and enable it after the "Save File" window has appeared. But I cannot intercept these events with a simple "synchrone" href.

I tried to process the request asynchronously with $http.get() but this time, I do not know how to serve the file the same way to the user when the process is done (the way Mega does it for example, for people who have already used it).

Thanks in advance !

PS: I know that, making the processing faster is another solution...but it is not really possible for now, and not the point :)

EDIT: Problem solved thanks to Ed answer, with some modifications (I don't know if is a "good" way to do this, but actually it works for me exactly the way I want).

$scope.processExport = function(campaignId) {
    if (!$scope.exportProcessing) {
        $scope.exportProcessing = true;
        $http.get('my_generating_url').success(function(response) {
            $scope.exportProcessing = false;
            $window.location.href = 'url_to_retrieve_the_file_with_' + response.fileName;
        }).error(function() {
            $scope.exportProcessing = false;
        });
    }
}

And the corresponding HTML:

<button ng-click="processExport(the_id)" ng-disabled="exportProcessing">Export</button>

And my_generating_url is just returning the file name when it has been successfully generated.

like image 806
Lebowski Avatar asked Sep 30 '22 17:09

Lebowski


1 Answers

What you are trying to do is quite difficult.

One approach is to modify the the way the server works: instead of accepting the request, then replying with the file itself when it is generated, the flow could be the following:

  1. Receive GET /exports?:id
  2. Generate the file locally (on the server) at an address like public/tmp/somefile
  3. Once the file is generated, reply to the request with the path to the file (www.server.com/tmp/somefile)

Then, on the client you could do something like this:

function getExportedFile(id){

  $scope.exporting = true;

  $http.get('/exports?id=' + id)
  .then( function (response) {
    $scope.exporting = false;
    $location.path(response.data);
  })
  .catch( function (error) {
    // TODO: handle errors
  });

}

Which would work with:

<button ng-click    = "getExportedFile(fileId)"
        ng-disabled = "exporting">
  Download Exported File
</button>
like image 59
Ed_ Avatar answered Oct 04 '22 04:10

Ed_