Day 30: Loading Bootstrap Modal Content via AJAX

This is the final installment in a 30 day series on Bootstrap and the MVC Framework. To see the rest of the series be sure to check out Day 0 for an index. I hope you have enjoyed following along! Smile

Here in our last post in the series we’re going to revisit our modal dialog confirmation box that pops up when a user tries to delete a record. At this point, regardless of the notification selected for delete, the user will see the same static dialog.

Loading Remote Content With Bootstrap’s Modal

There is built-in support for Bootstrap to load content into a modal, but there are some limitations. First, Bootstrap loads the content the first time the constructor is called on the modal. Secondly, the modal’s constructor is only ever called once, meaning, you can’t refresh the content without some extra script.

Rather than trying to put a square peg in a round hole, we can take the simpler approach of just loading the content with jQuery. After all, it’s clean, easy to understand, and at the end of the day the modal is just HTML.

This approach will work better for us for the following use case:

  • User selects to delete a notification
  • They cancel out of the dialog
  • The select a different notification to delete

At this point, the remote loading capabilities of Bootstrap’s modal break down and we’d have to get into hacky stuff that may not survive a minor version upgrade. Pass! In my opinion, the modal should have an overload that accepts a ‘remote url’ parameter.

If, however, you have a use case that doesn’t involve refreshing the dialog, I encourage you to check out the docs for using the built-in functionality.

Improving our Delete Confirmation

Rather than just giving a generic message, we’re going to instead load some content via AJAX. This will give us a chance to put a visual preview of the data that will be deleted in front of the user.

image

To accomplish this we’re going to need to make small change to our modal markup (in Views\Account_RenderNotifications.Modal.cshtml), as follows:

<div class=”modal-body” id=”notificationPreview”>
<p>Loading content…</p>
</div>

What I’ve done here is removed the content from the modal-body section of the markup and replaced it with a loading message.  I’ve also given the DIV an ID so that we can address it from JavaScript more directly.  Also, revisit your Views\Account_RenderNotifications.js.cshtml and update the confirmDelete method, as we’re now going to clear the contents and load the text dynamically.

function confirmDelete(id) {
currentNotificationId = id;
previewContainer.html(‘<p>Loading content…</p>’);
previewContainer.load(confirmUrl, { id: currentNotificationId });
$(‘#deleteConfirmModal’).modal(‘show’);
}

To pull that all together we need a couple more variable declarations at the top of the script. Here’s my final list of vars:

var readUrl = '@Url.Action(“MarkNotificationAsRead”)’;
var deleteUrl = '@Url.Action(“Delete”)’;
var confirmUrl = '@Url.Action(“GetNotification”)’;
var previewContainer = $(‘#deleteConfirmModal #notificationPreview’);
var currentNotificationId;

You’ll notice that I have added a confirm URL and captured the element (in previewContainer) that we are using for the confirm. This saves me from having to requery the DOM on each display of the dialog.

Adding the Controller Action

We’re going to use that same pattern for loading up the notification for the confirmation that we used for modifying and deleting. Let’s add a GetNotification method to our AccountController that has the following code:

public ActionResult GetNotification(int id)
{
var userNotification = GetUserNotifications().FirstOrDefault(n => n.NotificationId == id);

<span class="kwrd">if</span> (userNotification == <span class="kwrd">null</span>)
{
    <span class="kwrd">return</span> <span class="kwrd">new</span> HttpNotFoundResult();
}

<span class="kwrd">return</span> PartialView(<span class="str">"_RenderNotifications.ModalPreview"</span>, userNotification);

}

This time, we’ll be returning a partial view, as indicated in the code above, that will help us render the relevant content for the user to make their choice.

But hey…that code to load a single notification for the logged in user is crying for some refactoring, am I right?

Adding the Partial View

The controller is wired to pass the single notification to a partial view, which will essentially have the same information we had in the content section of the modal markup, but now we’ll also render in some notification-specific information. You can use your imagination on how this could be further extended with more complex objects in your own project.

Here are the contents of _RenderNotifications.ModalPreview.cshtml, which you should put into Views\Account:

@model SimpleSite.Models.Notification

<p>You have selected to delete this notification.</p>
<p>
<div class=”panel panel-warning”>
<div class=”panel-heading”>
<h4>@Model.Title</h4>
</div>
<div class=”panel-body”>
If this was the action that you wanted to do,
please confirm your choice, or cancel and return
to the page.
</div>
</div>
</p>

Next Steps

Wow! Thirty days of Bootstrap and MVC! It’s been a long 30 days…50 days actually, but no one could have foreseen the passing of my Grandma, my three-day fever of 103 degrees or the fact that this would end up running into my vacation for my 14th wedding anniversary and a most excellent trip to Seattle with my high school sweetheart (to whom I am married).

I have a few more things to add to this series, but for now we’ll call it a wrap. Thanks for your questions, suggestions, feedback and comments along the way!

Happy coding! Smile