top button
Flag Notify
    Connect to us
      Site Registration

Site Registration

Displaying A Progress Indicator During JQuery Ajax Calls

0 votes
347 views

Unlike traditional full page postback, where a user can easily understand that the page is being processed, Ajax based communication doesn't give any clue to the user about the processing being done in the background. This is especially important when the Ajax calls involve lengthy server side processing. It would be nice if you show some progress indicator or wait message to the end user while making Ajax calls. To that end this article shows one simple way of displaying such a progress indicator.

Have a look at the following figure:

image

The figure shows an ASP.NET Web Form that contains a Button control. Upon clicking the button an Ajax request is made to an ASP.NET Generic Handler (.ashx). At the same time an animated GIF is displayed as a progress indicator. The generic handler performs some processing and returns a success message to the Web Form. Once the Ajax request completes the animated GIF is hidden from the end user.

The markup of the Web Form looks like this:

<form id="form1" runat="server">
  <asp:Button ID="Button1" runat="server" Text="Make Ajax Call" />
  <div id="progress">
    <asp:Image ID="Image1" runat="server" ImageUrl="~/Progress.gif" />
  </div>
</form>

As you can see the Image control points to Progress.gif and is enclosed inside a <div> element whose ID is progress.

The generic handler (AjaxHandler.ashx) simply mimics a length operation by calling Sleep() method of Thread class. The following code shows how the AjaxHandler.ashx looks like:

public class AjaxHandler : IHttpHandler
{
  public void ProcessRequest(HttpContext context)
  {
    System.Threading.Thread.Sleep(10000);
    context.Response.ContentType = "text/plain";
    context.Response.Write("Data processed successfully!");
  }
  public bool IsReusable
  {
    get
    {
      return false;
    }
  }
}

The ProcessRequest() method makes the current thread sleep for 10 seconds. It then writes a success message onto the response stream.

The jQuery code that makes an Ajax call on the click of the button is shown below:

$(document).ready(function () {
  $("#progress").hide();

  $("#Button1").click(function (evt) {
    var options = {};
    options.url = "ajaxhandler.ashx";
    options.type = "GET";
    options.beforeSend = function () {
      $("#progress").show();
    };
    options.success = function (result) {
      alert(result);
    };
    options.error = function (xhr,status,err) {
      alert(err);
    };
    options.complete = function () {
      $("#progress").hide();
    };
    $.ajax(options);
    evt.preventDefault();
  });
});

The ready() handler hides the progress <div> element as soon as the page loads using hide() method. This way initially the animated GIF is kept hidden. The code then wires an event handler for the click event of Button1. The click event handler creates an options object. The url property of the options object points to the generic handler - AjaxHandler.ashx. The type property is set to GET indicating that a GET request is to be made. The important part is the beforeSend and complete handler functions. The beforeSend callback is called just before making an Ajax request. This is where you need to show the progress indicator (animated GIF in this case) to the end user. Inside the beforeSend function the progress <div> is shown to the user using show() method. The complete callback is called when the Ajax request completes (either successfully or with error). Inside the complete callback you hide the progress <div> using hide() method. The success callback simply shows the message returned from the server in an alert dialog. Similarly, the error handler shows the error message in an alert dialog. Finally, an Ajax call is made using jQuery $.ajax() method.

That's it! Run the web form and test whether the progress indicator is displayed as expected.

posted Nov 11, 2016 by Shivaranjini

  Promote This Article
Facebook Share Button Twitter Share Button LinkedIn Share Button


Related Articles

While uploading large files you may need to display the progress of the file upload operation to the end user. This can be done using HTML5 and jQuery UI's Progressbar widget. While HTML5 also has <progress> element that can be used to render a progress bar, jQuery UI's Progressbar widget offers more configuration and theming options. In this post you will use XMLHttpRequest (Level 2) object to upload files to the server. The XMLHttpRequest object now supports file upload related events such as progress that can be used to track file upload progress.

The following figure shows a sample Web Form that shows how the progress bar looks like:

image

The Web Form has a FileUpload server control that allows you to select one or more files. Clicking on the Upload button uploads the files on the server. To upload the files on the server you use XMLHttpRequest object instead of traditional postback. The files are uploaded in the background and the progress of the upload operation is displayed in the Progressbar widget. The progress bar also has a label that indicates the progress in percentages.

The Web Form consists of the following markup:

<form id="form1" runat="server">
        <asp:Label ID="Label1" runat="server" Text="Select File(s) to Upload :"></asp:Label>
        <br />
        <br />
        <asp:FileUpload ID="FileUpload1" runat="server" AllowMultiple="true" />
        <br />
        <br />
        <asp:Button ID="Button1" runat="server" Text="Upload" />
        <br />
        <br />
        <div id="progressbar" class="progressbar">
            <div id="progresslabel" class="progressbarlabel"></div>
        </div>
    </form>

As you can see the form primarily consists of a FileUpload server control, a Button and couple of <div> elements at the bottom. The outer <div> represents the Progressbar whereas the inner <div> represents the label of the progress bar.

Then add the following CSS classes for the outer <div> and the inner <div> respectively.

 .progressbar {
  width:300px;
  height:21px;
}
.progressbarlabel {
  width:300px;
  height:21px;
  position:absolute;
  text-align:center;
  font-size:small;
}

Now add the <script> sections to the head section as shown below:

 <script src="Scripts/jquery-2.0.0.js"></script>
<script src="Scripts/jquery-ui.js"></script>

As you can see the first <script> tag points to the jQuery library and the second <script> tag points to the jQuery UI library. Also add a reference to the CSS file needed by jQuery UI:

 <link href="jquery-ui.css" rel="stylesheet" />

Then add a new <script> block in the head section and write the following jQuery code in it:

 $(document).ready(function () {
  $("#Button1").click(function (evt) {
    var xhr = new XMLHttpRequest();
    var data = new FormData();
    var files = $("#FileUpload1").get(0).files;
    for (var i = 0; i < files.length; i++) {
      data.append(files[i].name, files[i]);
    }
    xhr.upload.addEventListener("progress", function (evt) {
    if (evt.lengthComputable) {
      var progress = Math.round(evt.loaded * 100 / evt.total);
      $("#progressbar").progressbar("value", progress);
    }
    }, false);
    xhr.open("POST", "UploadHandler.ashx");
    xhr.send(data);

    $("#progressbar").progressbar({
      max: 100,
      change: function (evt, ui) {
        $("#progresslabel").text($("#progressbar").progressbar("value") + "%");
      },
      complete: function (evt, ui) {
        $("#progresslabel").text("File upload successful!");
      }
    });
    evt.preventDefault();
  });
});

The above code consists of click event handler of Button1. Inside, the code creates an instance of XMLHttpRequest object (xhr) and a FormData object (data). It then obtains a list of files selected in the FileUpload control using files property of the DOM element. A for loop iterates through the files collection and with each iteration the file is added to the FormData object using its append() method. The first parameter of append() is the name of the file and the second parameter is the file itself.

Then progress event handler is wired to the upload object of the XMLHttpRequest object. This event is raised periodically during the file upload operation. The progress event handler uses event object properties such as lengthComputable, loaded and total to calculate the progress in percentages. The jQuery UI Progressbar is updated with this progress value. This is done by setting the value option of the progressbar widget to the progress value just calculated.

Then the open() method of XMLHttpRequest is called and the URL to an ASP.NET generic handler (UploadHandler.ashx) is specified. Then send() method is called to actually make the request and send the files to the server. The FormData object is passed as a parameter to the send() method.

Finally, the Progressbar widget is initialized on the progressbar <div> element. The configuration options namely max, change and complete are passed to the progressbar widget. The max option indicates the maximum value that can be displayed in the progress bar. the change options wires an event handler to the change event of the progressbar widget. The change event is raised whenever the value of the progressbar widget changes. The change event handler sets the text of the progressbarlabel <div> element to the value of the progressbar. The complete options wires an event handler for the complete event. The complete event is raised when the value reaches the max value of the progressbar widget. The complete event handler sets the text of the progressbarlabel <div> to "File upload successfully!".

Although not used in this example, you can also handle the load event of the XMLHttpRequest object to notify the user of the completion of the request.

Now add a generic handler (UploadHandler.ashx) to the project and add the following code to it:

public void ProcessRequest(HttpContext context)
{
  HttpFileCollection files = context.Request.Files;
  foreach (string key in files)
  {
    HttpPostedFile file = files[key];
    string fileName = file.FileName;
    fileName = context.Server.MapPath("~/uploads/" + fileName);
    file.SaveAs(fileName);
  }
  context.Response.ContentType = "text/plain";
  context.Response.Write("File(s) uploaded successfully!");
}

The generic handler receives the uploaded files in the Request.Files collection. Each file in the collection is an instance of HttpPostedFile class. A foreach loop iterates through the files collection and saves each PostedFile using the SaveAs() method. The files are saved in Uploads folder under the root folder of the web application. Once all the files are uploaded the generic handler sends a success message to the client.

That's it! Run the Web Form, select a few large files and click on the Upload button to see the progressbar widget in action.

READ MORE

Ajax stands for "Asynchronous JavaScript and XML".

JavaScript includes features of sending asynchronous http request using XMLHttpRequest object. Ajax is about using this ability of JavaScript to send asynchronous http request and get the xml data as a response (also in other formats) and update the part of a web page (using JavaScript) without reloading or refreshing entire web page.

The following figure illustrates the Ajax functionality.

Ajax

The jQuery library includes various methods to send Ajax requests. These methods internally use XMLHttpRequest object of JavaScript. The following table lists all the Ajax methods of jQuery.

jQuery Ajax MethodsDescription
ajax()Sends asynchronous http request to the server.
get()Sends http GET request to load the data from the server.
Post()Sends http POST request to submit or load the data to the server.
getJSON()Sends http GET request to load JSON encoded data from the server.
getScript()Sends http GET request to load the JavaScript file from the server and then executes it.
load()Sends http request to load the html or text content from the server and add them to DOM element(s).

The jQuery library also includes following events which will be fired based on the state of the Ajax request.

jQuery Ajax EventsDescription
ajaxComplete()Register a handler function to be called when Ajax requests complete.
ajaxError()Register a handler function to be called when Ajax requests complete with an error.
ajaxSend()Register a handler function to be called before Ajax request is sent.
ajaxStart()Register a handler function to be called when the first Ajax request begins.
ajaxStop()Register a handler function to be called when all the Ajax requests have completed.
ajaxSuccess()Register a handler function to be called when Ajax request completes successfully.

Advantages of jQuery Ajax:

  1. Cross-browser support
  2. Simple methods to use
  3. Ability to send GET and POST requests
  4. Ability to Load JSON, XML, HTML or Scripts

Let's look at an overview of important jQuery Ajax methods in the next section.

READ MORE

While using jQuery $.ajax you often need to perform some custom operations upon successful completion of the Ajax request. You may also need to handle errors (if any) that are thrown while issuing the request. To that end jQuery allows you to wire three callback functions as listed below:

  • success callback that gets invoked upon successful completion of an Ajax request
  • failure callback that gets invoked in case there is any error while making the request.
  • completion callback that gets invoked no matter a request completed with or without success.

Additionally, these callback functions can be attached in three distinct ways:

  • Local callbacks : Attaching callback functions as a part of $.ajax() call makes them local to the current Ajax request being made.
  • Global callbacks : Attaching callback functions at global level invokes them for all $.ajax() requests being issued from that page.
  • Promise callbacks : Attaching callback functions to the jqXHR object. This object implements Promise interface.

You can also use one or more of these ways together for an Ajax request.

Let's  quickly see how these three ways can be used. Suppose you you wish to make an Ajax request to a web form - target.aspx. The web form simply returns an HTML markup which is then displayed in a <div> element.

Using local callback functions

To attach local callback functions for success, failure and completion operations you pass them as a part of the settings to $.ajax() method. Consider the following code:

$.ajax({
  url: "target.aspx",
  type: "GET",
  dataType: "html",
  success: function (data, status, jqXHR) {
    $("#container").html(data);
    alert("Local success callback.");
  },
  error: function (jqXHR, status, err) {
    alert("Local error callback.");
  },
  complete: function (jqXHR, status) {
    alert("Local completion callback.");
  }
})

The above code shows various settings being passed to $.ajax() as a JavaScript object. Notice the success, error and complete settings. The success option points to a function that gets invoked upon the successful completion of a request. The success callnack receives three parameters viz. response data, HTTP status and jqXHR ovject. The first two parameters are straightforward. The third parameter is an object that wraps the underlying XMLHttpRequest object and is often referred as jqXHR object.

The error option points to a function that gets invoked in case an Ajax request fails. The error function receives three parameters viz. jqXHR object, HTTP status and exception object that was thrown. In a typical usage you will use the status and err parameters to display an error message to the end user.

The completion option points to a function that gets invoked once the request is complete - no matter whether it completes successfully or with an error. The completion callback receives two parameters viz. jqXHR object and HTTP status.

Using local callback functions is possible the most common approach and has an advantage of simple syntax and usage.

Using global callback functions

You can also wire global success, failure and completion callbacks with Ajax requests. These callbacks are global in that they are invoked for all Ajax requests arising from that page. They don't belong to a specific call. Consider t he following code:

$(document).ajaxSuccess(function (evt, jqXHR, settings) {
  alert("Global success callback.");
});

$(document).ajaxError(function (evt, jqXHR, settings, err) {
  alert("Global error callback.");
});

$(document).ajaxComplete(function (evt, XHR, settings) {
  alert("Global completion callback.");
});

The above code shows three methods of jQuery - ajaxSuccess(), ajaxError() and ajaxComplete() - that are invoked when the respective events happen. These functions are actually Ajax events of jQuery and hence receive an event parameter. Additionally, jqXHR object and settings that were used for making the Ajax request are passed to the event handlers. The error event handler also receives the exception that was throws.

Global callback functions are useful when you wish to perform some common task for all the Ajax requests being issued from the page. They are also useful if you wish to use $.get() and $.post() instead of $.ajax(). Since these methods don't accept error handler as a part of their signature you can't trap errors. Wiring global ajaxError() will provide an error handler for these methods also. 

Using Promise object

A bit modern way to wire these callback functions is to use JavaScript Promise object. A JavaScript Promise is an object that represents a result of an Ajax request (in fact any asynchronous request). The $.ajax() method returns jqXHR object and jqXHR implements the Promise interface. Hence, upon calling $.ajax() you can use done(), fail() and always() methods of the Promise interface to wire the respective callback functions. The following code illustrates how this is done:

var jqXHR = $.ajax({
  url: "target.aspx",
  type: "GET",
  dataType: "html",
}).done(function (data, status, jqXHR) {
  $("#container").html(data);
  alert("Promise success callback.");
}).fail(function (jqXHR,status,err) {
  alert("Promise error callback.");
}).always(function () {
  alert("Promise completion callback.");
})

The above code calls $.ajax() as before however it doesn't provide any local callback functions. The $.ajax() return a jqXHR object and three methods done(), fail() and always() are used to wire callback functions to the respective operations. The function supplied to done() is invoked with the Ajax request completes successfully. The function supplied to fail() is invoked if the request fails. The function supplied to always() is invoked irrespective of whether the request was successful or not. The done() function receives three parameters viz. response data, HTTP status and jqXHR object. The fail() function receives jqXHR object, HTTP status and the error thrown during the request. Finally, the always() function receives the same parameter as that of done() if the request succeeds otherwise it receives the same parameters as that of fail().

READ MORE

While using jQuery $.ajax you often need to perform some custom operations upon successful completion of the Ajax request. You may also need to handle errors (if any) that are thrown while issuing the request. To that end jQuery allows you to wire three callback functions as listed below:

  • success callback that gets invoked upon successful completion of an Ajax request
  • failure callback that gets invoked in case there is any error while making the request.
  • completion callback that gets invoked no matter a request completed with or without success.

Additionally, these callback functions can be attached in three distinct ways:

  • Local callbacks : Attaching callback functions as a part of $.ajax() call makes them local to the current Ajax request being made.
  • Global callbacks : Attaching callback functions at global level invokes them for all $.ajax() requests being issued from that page.
  • Promise callbacks : Attaching callback functions to the jqXHR object. This object implements Promise interface.

You can also use one or more of these ways together for an Ajax request.

Let's  quickly see how these three ways can be used. Suppose you you wish to make an Ajax request to a web form - target.aspx. The web form simply returns an HTML markup which is then displayed in a <div> element.

Using local callback functions

To attach local callback functions for success, failure and completion operations you pass them as a part of the settings to $.ajax() method. Consider the following code:

$.ajax({
  url: "target.aspx",
  type: "GET",
  dataType: "html",
  success: function (data, status, jqXHR) {
    $("#container").html(data);
    alert("Local success callback.");
  },
  error: function (jqXHR, status, err) {
    alert("Local error callback.");
  },
  complete: function (jqXHR, status) {
    alert("Local completion callback.");
  }
})

The above code shows various settings being passed to $.ajax() as a JavaScript object. Notice the success, error and complete settings. The success option points to a function that gets invoked upon the successful completion of a request. The success callnack receives three parameters viz. response data, HTTP status and jqXHR ovject. The first two parameters are straightforward. The third parameter is an object that wraps the underlying XMLHttpRequest object and is often referred as jqXHR object.

The error option points to a function that gets invoked in case an Ajax request fails. The error function receives three parameters viz. jqXHR object, HTTP status and exception object that was thrown. In a typical usage you will use the status and err parameters to display an error message to the end user.

The completion option points to a function that gets invoked once the request is complete - no matter whether it completes successfully or with an error. The completion callback receives two parameters viz. jqXHR object and HTTP status.

Using local callback functions is possible the most common approach and has an advantage of simple syntax and usage.

Using global callback functions

You can also wire global success, failure and completion callbacks with Ajax requests. These callbacks are global in that they are invoked for all Ajax requests arising from that page. They don't belong to a specific call. Consider t he following code:

$(document).ajaxSuccess(function (evt, jqXHR, settings) {
  alert("Global success callback.");
});

$(document).ajaxError(function (evt, jqXHR, settings, err) {
  alert("Global error callback.");
});

$(document).ajaxComplete(function (evt, XHR, settings) {
  alert("Global completion callback.");
});

The above code shows three methods of jQuery - ajaxSuccess(), ajaxError() and ajaxComplete() - that are invoked when the respective events happen. These functions are actually Ajax events of jQuery and hence receive an event parameter. Additionally, jqXHR object and settings that were used for making the Ajax request are passed to the event handlers. The error event handler also receives the exception that was throws.

Global callback functions are useful when you wish to perform some common task for all the Ajax requests being issued from the page. They are also useful if you wish to use $.get() and $.post() instead of $.ajax(). Since these methods don't accept error handler as a part of their signature you can't trap errors. Wiring global ajaxError() will provide an error handler for these methods also. 

Using Promise object

A bit modern way to wire these callback functions is to use JavaScript Promise object. A JavaScript Promise is an object that represents a result of an Ajax request (in fact any asynchronous request). The $.ajax() method returns jqXHR object and jqXHR implements the Promise interface. Hence, upon calling $.ajax() you can use done(), fail() and always() methods of the Promise interface to wire the respective callback functions. The following code illustrates how this is done:

var jqXHR = $.ajax({
  url: "target.aspx",
  type: "GET",
  dataType: "html",
}).done(function (data, status, jqXHR) {
  $("#container").html(data);
  alert("Promise success callback.");
}).fail(function (jqXHR,status,err) {
  alert("Promise error callback.");
}).always(function () {
  alert("Promise completion callback.");
})

The above code calls $.ajax() as before however it doesn't provide any local callback functions. The $.ajax() return a jqXHR object and three methods done(), fail() and always() are used to wire callback functions to the respective operations. The function supplied to done() is invoked with the Ajax request completes successfully. The function supplied to fail() is invoked if the request fails. The function supplied to always() is invoked irrespective of whether the request was successful or not. The done() function receives three parameters viz. response data, HTTP status and jqXHR object. The fail() function receives jqXHR object, HTTP status and the error thrown during the request. Finally, the always() function receives the same parameter as that of done() if the request succeeds otherwise it receives the same parameters as that of fail().

READ MORE

In this article I have taken the example of submitting a contact form consisting of name and address field.

Step 1: Create a New Project.

Go To File -> New -> Select Empty and Checked MVC -> OK



Step 2: Now Right Click on Controllers -> Add -> New Controller -> Name it as HomeController



Step 3: In the HomeController there is Index method create View for it.



Step 4: Now right click on Models -> New -> Class.



In the Contact class write the field which will be on your form. In my form I want only three fields so I have written it as:



Step 5: Go to the Index.cshtml and write the code for form in the body element and don’t give any action to form.



Step 6: Now to submit the form asynchronously we use JQuery. Write the code for it in <script> in the head or you can write it in external file also ,just don’t forgot to give its reference on the page.

In the code we are using the jquery submit event for submitting the form it actually overrides the form submit action. In the $.post(‘url’,serialized form data).success(function(response){//to do}.

The success event get triggers if the data posted successfully. It takes response from the server I am giving alert of the response here.

 

Step 7: Now we have to write controller method to get the form data. Write method in the HomeController I have named it ‘submit’ as I gave in the url. And the submit method takes model contact class as argument which gets filled with the form data; after submitting the form also returns nothing. Give [HttpPost] Annotation to the submit method. Also we are writing in the response that ‘form is submitted successfully’ using Response.writemethod.which gets send to the success event of $.post.



Step 8: Now put breakpoint at your submit method and start debugging your Index.cshtml page. Fill the fields and submit.



After submitting you will find the submitted data in controller method argument and further you will get the alert.



Run

READ MORE
...