Home / AJAX

How Do I Display a Dialog Box?

RSS
Modified on 2010/11/06 16:25 by James Chambers Categorized as Uncategorized

Problem

Certain situations require showing a popup window in my ASP.NET MVC application. The dialog box has to have the same look-and-feel as the rest of my web site. How can I achieve this?

Solution

jQuery UI provides a dialog component that is themed in a similar fashion as the rest of the controls in the library. Becuase it is composed of simple HTML constructs, it is also easy to use it to show and collect data from and destined for the ASP.NET MVC Framework.

Preparing Our View for a Dialog

The first step is creating the elements required in order to use a jQuery UI dialog. Thankfully, this is a fairly trivial task.
<div id="dialog">Hello, Dialog.</div>
<script>
$(function(){
  $("#dialog").dialog();
});
</script>

Basically, all that's required is a container div and a call to dialog(). At some point we're going to need to have an ethics-based discussion around hourly billing when we use jQuery.

Image

Now, while this gives us a great start and a very easy way to using the component, we're obviously missing some basic features including buttons and a title. If you were to take the code above and run it, you would also find that the dialog opens on page load - not likely what you're looking for. Let's dig a little deeper and see some of the other functionality and features.

Displaying the Dialog on Demand

Let's flesh out that div a little more and get some more content in it. We'll specify the title of the dialog in the tag, and add a paragraph of text to the body of the div.
<div id="dialog-block" title="ASP.NET MVC Plays Nice with jQuery UI">
    <p>
        If you were wondering if there was a way to make jQuery UI and 
        the ASP.NET MVC Framework play nicely together, you don't have to
        wonder any longer! This dialog box is displayed from a view created
        in the MVC Framework.
    </p>
</div>

We can control the width of the dialog and supress the default behavior to open instantly by specifying a couple of options when we call dialog(). The other thing we're going to do here is to declare a button by specifying a key/callback pair and passing it into the options object. The callback can be a declared or anonymous function (as it is here).
// create our dialog
$('#dialog-block').dialog({
    autoOpen: false,
    width: 400,
    buttons: {
        "Sweet!": function () {
            closeDialog($(this))
        }
    }
});

With these options in place, our dialog will look something like this when it is displayed:

Image

Our dialog no longer opens on it's own and we're going to need a way for users to open it. While you could use any event to display the pop-up, here we're going to add a button to our page and then use the click event to display the dialog.
<button id="dialog-button"><span class="ui-icon ui-icon-newwin"></span>Yes, this one!</button>

And finally, we'll add the code for our click event handler to the script block we created above.
// the button to open the dialog
$('#dialog-button').button()
    .click(function () {
        $('#dialog-block').dialog('open');
    });

Try Me!

Load Dialog Content via Ajax for Page Performance

If you have some content that only needs to be displayed on-demand you can see performance gains by delay-loading these sections. This is where Ajax and the MVC Framework really shine. By creating a partial view that handles the long-loading content - and only calling it to be displayed when requested by the user - you can improve the overall performance of the page.

We don't need to change much to get this to work in our previous example. Remember that these are just elements in the DOM, so we can access them and manipulate them just as you would any other. If you understand the concept of loading content with Ajax already, this will seem quite straightforward.

The first thing we'll do is add a spot for the content to be hosted in the div we'll use for the dialog by creating a p element with an ID of additional-content.
    <div id="dialog-block" title="Delay-loading Content">
        <p>
            <!-- Text in dialog -->
        </p>
        <p id="additional-content"></p>
    </div>

Next, we'll modify our click event handler a little to take care of some setup for us. In this case, we're going to set a loading message into our placeholder, call dialog('open') and then make the call to the slow-loading content.
// dialog-button
$('#dialog-button').button().click(function () {

// reset our loading pane $('#additional-content') .html('Loading additional content...');

// open the dialog $('#dialog-block').dialog('open'); setTimeout("updateDialog()", 1000); // simulate some load time });

You obviously wouldn't use the setTimeout in a production scenario; here we're just trying to simulate here a long-running process with JavaScript. We call a method named updateDialog() which would make the call to a PartialView and load it in our placeholder. In the script below, I've also added some animations to jazz up the content loading when the call to the controller is complete.
function updateDialog() {
    var elem = $('#additional-content');
    elem.slideUp('200', function () {
        elem.load("AdditionalContent", '', function () {
            elem.addClass('bold-announcement');
            elem.slideDown();
        })
    });
}

Finally, the action on the controller is called to refresh the page with a partial view. The method is called with no parameters and is loaded into the additional-content element on the page per the above script. We might have code like this in our controller:
public PartialViewResult AdditionalContent()
{
    // here we could do something interesting, like load data from a remote machine
    // or query some live equipment in the field, etc...

// IRemoteService service = new FactoryRemoteService(); // var status = service.GetServoStatuses(); // return PartialView(status);

// ...or we can do something simple, like returning static content return PartialView(); }

See it in action: Try Me!

You can see this being of benefit, for example, if you're checking inventory on a third-party vendor's system and there's a long wait time. Given a list of parts, you're not likely to order them all, so you don't need to load the inventory levels for all of the items either.

Sending the Dialog Results to an MVC Action

Let's look at a slightly more complicated scenario where we use the dialog to capture some input from the user, then use those values to drive an update to a page. Consider a web page that lists homes and the user is given the option to set some properties to limit the types of listings that are displayed.

Image

There are a number of things we're going to need to make this come together:
  • Our base page, with a button to launch the dialog
  • A div element set up with the input controls we want the user to manipulate
  • A click event handler that POSTs the data back to the server to get new results
  • A placeholder to display the home listings
  • A controller action that returns a partial view of home listings, and finally,
  • Some background functionality that allows searches and returns the homes

The core of our page will contain the button, the placeholder for the home listings and the dialog. We're also going to add a div that will be displayed when we're loading new data.
<button id="filter-homes">Filter Homes</button>

<div id="loading-content" style="display:none;"> <img src="<%= Url.Content("~/areas/dialog/Content/ajax-loader.gif") %>" alt="" /> Loading data... </div>

<div id="home-list"> <% Html.RenderAction("ListHomes"); %> </div> <div id="form-dialog"> <h3 id="form-header">Select your options to filter homes</h3> <div id="form-body"> <label for="maxPrice">Maximum House Price:</label> <input type="text" id="maxPrice" style="border:0; color:#f6931f; font-weight:bold;" /> <div id="value-slider"></div>

<label for="minBedrooms">Minimum Number of Bedrooms:</label> <input type="text" id="minBedrooms" style="border:0; color:#f6931f; font-weight:bold;" /> <div id="room-slider"></div> </div> </div>


I'm using some slider controls on the div. These are part of jQuery UI and will be covered in greater detail in a later article in this series.

You'll notice on the screen shot above that the rest of the page is grayed out and the dialog has been displayed as modal on the page. We'll incorporate the modal option and a close event handler when we instantiate the dialog.
// create our dialog
$('#form-dialog').dialog({
    autoOpen: false,
    width: 400,
    modal: true,
    buttons: {
        "Filter": function () {
            $(this).dialog("close");
        }
    },
    close: function () {
        refreshHomes($("#value-slider").slider("value"), $("#room-slider").slider("value"));
    }
});

The close handler is an anonymous method that captures the value of the sliders and passes them to our refreshHomes() function.
        function refreshHomes(price, beds) {
            $("#loading-content").slideDown('fast', function () {
                $.post(
                    "SearchHomes",
                    { maxPrice: price, minBedrooms: beds },
                    function (data) {
                        $("#home-list").html(data);
                        $("#loading-content").slideUp();
                    });
            });
        }

The POST is handled by a controller action that returns a partial view with the filtered listing of homes.
[HttpPost]
public PartialViewResult SearchHomes(HomeSearch criteria)
{
    HomeRepository repository = new HomeRepository();
    var model = repository.FindHomes(criteria);
    return PartialView("HomeList", model);
}

One more thing. If you're looking closely, you'll notice that the controller action accepts a HomeSearch object. This is a simple class that I defined with two properties, maxPrice and minBedrooms. This parameter is examined at runtime and, because the property names match the POSTed form parameters, the MVC framework instatiates a HomeSearch object and calls this method accordingly.

Give it a whirl: Try Me!

Wrapping Up

Dialogs are something that, for years, we had to roll a new version of each time we started on a new site. With jQuery UI we can use dozens of community-created themes (or our own) and instantly have our dialogs up and running. When combined with ASP.NET MVC we can also improve performance, augment the experience for end users and, more importantly, maximize our development time.

About the Author

James Chambers is a Senior Software Developer in Canada, where he once made a snowblower out of three electric toothbrushes, a shovel and duct tape. His development passions are fueled by new tech, new tools and mentoring others. Follow his coding adventures at Mister James.
  Name Size
- jq-dialog-filter.PNG 92.14 KB
- jq-dialog-hello.PNG 4.53 KB
- jq-dialog-options.PNG 27.03 KB