0

I would like to toggle a spinner on a form submission that returns a FileResult from the server after some processing. However, since I do not refresh the page, the spinner does not get disabled automatically with my current implementation.

How can I detect the successful response with JavaScript to download my file normally, and disable the spinner after it is generated?

I would like to avoid roundabout methods that involve refreshing the page or downloading the file using JavaScript, if possible.

Below is a modified version of my page as a code snippet. In my actual code, I use @using (Html.BeginForm()) instead of a raw HTML form.

    window.onload = function() {
      $("form").on("submit", function() {
        startSpinner();
      });
    };

    window.onbeforeunload = function() {
      stopSpinner();
    };

    function startSpinner() {
      $(".overlay").css("display", "initial");
    }

    function stopSpinner() {
      $(".overlay").css("display", "none");
    }
.overlay {
  position: fixed;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
  background: rgba(0, 0, 0, 0.3);
  z-index: 9999;
}
.loader {
  position: fixed;
  left: 50%;
  top: 50%;
  margin-left: -50px;
  margin-top: -50px;
  width: 100px;
}
.loader:before {
  content: '';
  display: block;
  padding-top: 100%;
}
.circular {
  -webkit-animation: rotate 2s linear infinite;
  animation: rotate 2s linear infinite;
  height: 100%;
  -webkit-transform-origin: center center;
  transform-origin: center center;
  width: 100%;
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
  margin: auto;
}
.path {
  stroke-dasharray: 1, 200;
  stroke-dashoffset: 0;
  -webkit-animation: dash 1.5s ease-in-out infinite, color 6s ease-in-out infinite;
  animation: dash 1.5s ease-in-out infinite, color 6s ease-in-out infinite;
  stroke-linecap: round;
}
@-webkit-keyframes rotate {
  100% {
    -webkit-transform: rotate(360deg);
    transform: rotate(360deg);
  }
}
@keyframes rotate {
  100% {
    -webkit-transform: rotate(360deg);
    transform: rotate(360deg);
  }
}
@-webkit-keyframes dash {
  0% {
    stroke-dasharray: 1, 200;
    stroke-dashoffset: 0;
  }
  50% {
    stroke-dasharray: 89, 200;
    stroke-dashoffset: -35px;
  }
  100% {
    stroke-dasharray: 89, 200;
    stroke-dashoffset: -124px;
  }
}
@keyframes dash {
  0% {
    stroke-dasharray: 1, 200;
    stroke-dashoffset: 0;
  }
  50% {
    stroke-dasharray: 89, 200;
    stroke-dashoffset: -35px;
  }
  100% {
    stroke-dasharray: 89, 200;
    stroke-dashoffset: -124px;
  }
}
@-webkit-keyframes color {
  100%, 0% {
    stroke: #d62d20;
  }
  40% {
    stroke: #0057e7;
  }
  66% {
    stroke: #008744;
  }
  80%,
  90% {
    stroke: #ffa700;
  }
}
@keyframes color {
  100%, 0% {
    stroke: #d62d20;
  }
  40% {
    stroke: #0057e7;
  }
  66% {
    stroke: #008744;
  }
  80%,
  90% {
    stroke: #ffa700;
  }
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="overlay" style="display: none;">
  <div class="loader">
    <svg class="circular" viewBox="25 25 50 50">
      <circle class="path" cx="50" cy="50" r="20" fill="none" stroke-width="5" stroke-miterlimit="10" />
    </svg>
  </div>
</div>

<!-- Some fields... -->
<form>
  <button type="submit" class="btn btn-primary" id="analysis-submit-btn">Submit</button>
</form>

Typical controller method:

var myPackage = myFunction(myParameters);
var myFileName = "filename";
return File(myPackage, MediaTypeNames.Application.Octet, myFileName);

1 Answer 1

2

Since you are doing a full POST, instead of an ajax call and are returning a file, instead of refreshing the view, you are somewhat limited to what you can do.

Looks like someone came up with a fairly innovative solution to this very problem:

http://dejanstojanovic.net/jquery-javascript/2015/march/detect-when-file-download-request-is-finished-with-jquery/

It involves setting a cookie from the controller that returns the file. Then when you submit the form, you start checking to see if you have that cookie. If you have that cookie, it means the request has been sent down to the user.

Sign up to request clarification or add additional context in comments.

2 Comments

I am not opposed to using AJAX either, but the problem in that case is that I am binding input fields to a model, and there doesn't seem to be a convenient way to invoke the model binder and process my form in the same way as I would a full POST. It looks like both approaches have their own issues, so which one do you think would be simpler?
I believe that you are not allowed to download a file when doing an AJAX call, so that rules out AJAX.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.