Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

jQuery Modal Dialog with Dynamic Content

0.00/5 (No votes)
6 Nov 2012 1  
Implement a jQuery dialog window (modal or normal) that can contain truly dynamic content.

Introduction

Popping up a dialog window is a very common scenario in web development, especially in a parent-child kind of UI setup. Most of the times it might contain mostly static content and the dynamic elements in it will be a few text changes. There are use-cases where a jQuery dialog window should open up very dynamic content (including elements rendered) based on certain criteria selected in the parent page.

In the first part of this article, I will demonstrate how to implement a jQuery dialog window (modal or normal) that can contain truly dynamic content, in which the contents are loaded from a totally different aspx/html page. In the second part of the article, I will show you how to do a postback from a jQuery dialog window such that the dialog window does not close automatically (which normally is the case) once the postback is over. Not only that, I will also show you updated content in the jQuery dialog as a result of the postback.

Background

Sometime back we had a requirement to popup a Dialog window with truly dynamic content. Though initially it was thought to be done using native IE modal popups, as it was easy to do it, we later decided to develop the same using jQuery UI Dialog framework.

Technologies and tools used:

  • Visual Studio 2010 and C# to develop the samples.
  • jQuery js files from the version 1.7.1
  • jQuery UI js files from the version 1.8.17

Using the Code

For the sake of simplicity of the demo of the concept, I have used a very simple use case scenario. The parent page consists of 2 text boxes and a button. The user can enter the number of rows and columns in the textboxes. When the user clicks on the button, the jQuery dialog opens up with a table with that many rows and columns specified by the user.

The point here is that, based on the inputs from the user we can load a modal window with dynamic content like generating a table on the fly from the server side. Remember that since the table is rendered from the server side, it gives the user access to all server side data – session data, .NET cache data, Database server data, remote service data – you name it. The user can build an UI layout of his choice using data sitting in a remote place into a jQuery modal Dialog window!

So enough of all the lecture, let’s see some code!

Loading Contents of an ASPX Page into a jQuery Dialog Window

First I will start with showing you how to load a dialog window with some dynamic content.

$("#LoadDialogButton").off("click");
$(document).on("click", "#LoadDialogButton", function () {

    var url = "DialogContentPage.aspx";
    var divId = " #MainContentDiv";

    var q1 = "?inp1=" + $("#Input1").val();
    var q2 = "&inp2=" + $("#Input2").val();

    url = url + q1 + q2 + divId; //url in the form 'DialogContentPage.aspx?inp1=xx&inp2=yy #MainContentDiv'

    $('<div id=DialogDiv>').dialog("destroy");

    $('<div id=DialogDiv>').dialog({
        dialogClass: 'DynamicDialogStyle',
        modal: true,
        open: function () {
            $(this).load(url);           
        },
        close: function (e) {
            $(this).empty();
            $(this).dialog('destroy');
        },
        height: 350,
        width: 540,
        title: 'Dynamic Dialog'

    });
});

If you look at the code above, it is typical jQuery UI syntax of loading a jQuery modal dialog. But if you look at the ‘open’ attribute in it, it makes a request to a URL. The URL is built in the format:

DialogContentPage.aspx?inp1=xx&inp2=yy #MainContentDiv

What it does over here is that it makes a request to this aspx page with the parent page inputs (rows & columns) as query strings. The server generated the table using the inputs and renders back the generated html. The generated HTML contains a div with the id "MainContentDiv". Everything that is generated at the server is within this div. The contents of this div are simply loaded into the jQuery modal window.

Let’s see the code in the parent aspx page:

<asp:UpdatePanel ID="UpdatePanel" runat="server">
        <ContentTemplate>
            <div>

                <label for="Input1">
                    Rows
                    <input type="text" id="Input1" value="1"/>
                </label>

                <label for="Input2">
                    Columns
                    <input type="text" id="Input2" value="2"/>
                </label>

                <br />
                <br />
                <input type="button" id="LoadDialogButton" value="Open Dialog" class="ButtonStyle" />

                <asp:Button ID="ServerButton" Text = "Server Dummy Button" runat="server" OnClick="DoSomethingOnServer"/>
            </div>

        </ContentTemplate>
    </asp:UpdatePanel>

As you can see, I have put everything under an UpdatePanel and it has a dummy server side button. This is not actually required for this demo to work, but I have put the whole jQuery Dialog Window loading button (button with id LoadDialogButton) under this to show you a point.

If you have noticed the way I have bound the click event of the button ‘LoadDialogButton’, I have used the syntax:

$(document).on("click", "#LoadDialogButton", function () {

instead of the most commonly used:

$("#LoadDialogButton").click(function () {

The 2nd syntax would have worked perfectly well in this demo if I haven’t used the UpdatePanel. But there can be situation where you will use the UpdatePanel in a real scenario, but also want the jQuery events to work.

The asp:UpdatePanel replaces the original content with the results from the server, and what it means that all the previously hooked jQuery events using the jQuery ‘click’ syntax will not work anymore – You can try this out. This is where the jQuery.on syntax of binding a click event helps you.

As of jQuery 1.7, the .on() method is the preferred method for attaching event handlers to a document. For earlier versions, the .bind() method (‘Click syntax’) is used for attaching an event handler directly to elements. Handlers are attached to the currently selected elements in the jQuery object, so those elements must exist at the point the call to .bind() occurs. (Source)

Now on click of the ‘Open Dialog’ button, it opens up a jQuery Dialog with dynamically generated table as shown below:

I will come to details of what happens when you click on the ‘Evaluate’ button in the last section of this article.

Oh, I almost forgot, you need to do one more thing for this example to work correctly. As you can in this example that the entire contents of the jQuery Modal window is loaded from DialogContentPage.aspx. The problem here is that if you close the modal window and open it again, after changing some inputs, say number of rows or columns changed, you will see that it has opened with a layout which was previously opened!

I think you have guessed what has happened, yes, the browser has cached the previous page and hence opened up that. You can easily avoid this by adding some more code in the Page_Init of the DialogContentPage.aspx. Let's see that

protected void Page_Init(object sender, EventArgs e)
{
// Stop Caching in IE
Response.Cache.SetCacheability(System.Web.HttpCacheability.NoCache);

// Stop Caching in Firefox
Response.Cache.SetNoStore();
}

What it does is, it adds the following response headers, and it makes sure that this particular page is never cached (atleast on IE and Firefox)

Cache-Control: no-cache, no-store
Pragma: no-cache
Expires:-1

I have captured the same in Fiddler, you can see that below:

Loading a div with server side components into a jQuery Dialog Window

Another scenario where we usually encounter is when we will have to load a jQuery Dialog window with server side contents. In this example, I have a div ‘LocalDialogModal’ which has a asp:Label, asp:TextBox, and an asp:Button. The asp:button has a server side method "SaveEmployeeBtn_Click".

I am going to show you how to load this div into a jQuery Modal Dialog and still be able to call the server side method on the click of the asp:button

Have a look at the div element placed within the form tag of the parent page:

<div id='LocalDialogModal' style="display: none">
        <span style="font-style: italic; font-size: x-small; color: Gray;">Note: This is a
            jQuery modal dialog which does not have dynamic content but this content has server
            side elements, and is defined in the parent page
            <br />
            <asp:Label ID="lblNewName" runat="server" AssociatedControlID="TextBox_NewEmployeeName"

                Text="Employee Name: "></asp:Label>
            <asp:TextBox ID="TextBox_NewEmployeeName" runat="server" Width="100%"></asp:TextBox><br />

            <br />
            <asp:Button ID="SaveEmployee_Button" OnClick="SaveEmployeeBtn_Click" runat="server"
                Text="Save" CssClass="ButtonStyle" Style="margin: 0px;" /><br />

 </div>

Now have a look at the jQuery definition of the Modal Dialog to be created with this div:

$("#LocalDialogModal").dialog({
        dialogClass: 'dialogStyle',
        autoOpen: false,
        resizable: false,
        draggable: false,
        modal: true,

        open: function (type, data) {
            $(this).parent().appendTo("form");
        },

        width: 500,
        height: 238,
        title: "Save Employee"
    });

If you closely watch the code snippet above, it is almost same as how you define any jQuery Modal dialog, but with a small difference in the ‘open’ attribute. We have a statement like this:

$(this).parent().appendTo("form");

This line is important to make the server side button in the div to function correctly. What that line does is, it appends the whole content of the rendered html into the existing form tag of the parent page.

Now, does that confuse you? Yes, it confused me too. If you look at the parent.aspx, the div ‘LocalDialogModal’ is already under the form tag. Why do you have to do an ‘append’ again?

The answer lies in how jQuery handles the dialog windows by default. Even though you have put the div within the form tag, when you load them, the whole div is rendered outside the form tag, by default. Hence all the server side elements that got rendered will not work, if it is not under a form tag.

I will show the rendered html if I haven’t put that one line:

$(this).parent().appendTo("form");

And remember that, this is the default behavior of the jQuery dialog window:

Now when we put the code to append the ‘localDialogModal’ div into the form tag, the rendered HTML looks like below:

Now that the server side button comes within the form tag, clicking on it will call the server side method "SaveEmployeeBtn_Click" without any problem.

Calling a server side method asynchronously from a jQuery Dialog Window

To achieve async server calls from within the jQuery Dialog window, we might consider putting the contents of the jQuery Dialog within an asp:UpdatePanel – but this will not work correctly most of the time. You might encounter problems like Dialog window getting closed soon after the postback, not able to see updated contents in the Dialog window itself, the dialog itself getting unhooked, etc.

I am going to show you how to call the a server side method asynchronously without having to worry about the asp:updatePanel nuances associated with jQuery Dialogs.

Let’s consider the first example shown here, wherein we load a totally different aspx contents into a jQuery Dialog window invoked from a parent page. It will be very straightforward to assume that we will have buttons in the child aspx content that has to make server side calls.

Let’s see the code in the DialogContentPage.aspx:

<form id="form1" runat="server">
    <div id="MainContentDiv">
        Dynamic Dialog Page loaded!
        <asp:PlaceHolder ID="DynamicPlaceholder" runat="server"></asp:PlaceHolder>

        <input type="button" id="EvaluateButton" value="Evaluate" class="ButtonStyle" />
        <br /><br />

        <div>
            <asp:Label ID="ResultLabel" runat="server" Height="60px" Width="400px" Style="display: none"></asp:Label>

        </div>
    </div>
 </form>

The asp:Placeholder will hold the table that is generated at runtime based on the inputs from the user (in our case) or any data that is available with you at the server.

We have a button ‘EvaluateButton’. I am going to show you how to call a server side method on the click of this button along with some inputs, do some operations on the server and then update the results on the jQuery Dialog window itself (without closing it) – all asynchronously.

Let’s bind a jQuery method to be called on the click of this button:

$(document).on("click", "#EvaluateButton", function () {

        var inputArray = new Array();
        $("#DynamicTable").find("input").each(function (index) {
            //alert(this.id);
            inputArray[index] = $(this).val();
        });

        var inputArrayList = "{ inputArray: " + JSON.stringify(inputArray) + "}";

        $.ajax({
            type: "POST",
            dataType: "json",
            contentType: "application/json",
            url: "DialogContentPage.aspx/Evaluate_Click",
            data: inputArrayList,
            success: function (data) {
                //debugger;

                if (data.d.indexOf("Error") != -1) {
                }
                else {
                    $("#ResultLabel").show();
                    $("#ResultLabel").text("Sum of all the contents is: " + data.d);
                }
            },
            error: function (e, ts, et) {
                //debugger;
                alert(ts);
            }
        }); //ajax func end
    });

What is being done here is very straightforward. I take all the inputs in the textboxes within the table generated dynamically, and created a JSON string.

And then, I call a url "DialogContentPage.aspx/Evaluate_Click", with this JSON string as input.

So what is this url represent? It represents a web method ‘Evaluate_Click’ defined at the server in DialogContentPage.aspx. Ok, Let’s see that:

[System.Web.Services.WebMethod]
public static string Evaluate_Click(string[] inputArray)
{
        string result = string.Empty;

        try
        {
            int resultInt = 0;
            foreach (var item in inputArray)
            {
                var input = int.Parse(item);
                resultInt += input;
            }

            result = resultInt.ToString();
        }
        catch (Exception exp)
        {
            result = "error";
        }
        return result
}

This method is very straightforward – it takes an input of string array, and does something as simple as adding it up all together. The point here is that, since this is done at the server side, you can do a whole lot of complex stuff to achieve some result.

Also remember 2 things:

  • This method should be static and should be decorated by the attribute [System.Web.Services.WebMethod]
  • The input that it takes should be of the same name as defined in the earlier JSON creator method shown below:
var inputArrayList = "{ inputArray: " + JSON.stringify(inputArray) + "}";

Rest everything is straightforward – Once the web method returns the results successfully, I append the result to the ResultsLabel.

I have attached the source code of all the examples shown in this article.

Points of Interest

These are very frequently occurring scenarios that a beginner in jQuery might encounter and may lose a lot of time trying to achieve it without issues.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here