Using Bootstrap Dialogs in ASP.NET MVC






4.14/5 (4 votes)
This tip describes an approach to use Bootstrap dialogs in ASP.NET MVC.
Introduction
There are no standards of how to use bootstrap dialogs in ASP.NET MVC.
Often, many questions appear on a phase of implementation:
- How to create dialogs?
- Where dialogs should be placed in HTML?
- How to fill dialogs with dynamic information?
- How to subscribe to dialog events?
This tip gives an approach to organize and use bootstrap dialogs effectively.
Utility Function
Let’s create a utility function which will be used to create Bootstrap Dialogs.
DialogUtils = {
ShowDialog: function(dialogOptions) {
var container = $("[data-dialog-container=\"" + dialogOptions.url + "\"]");
/* Check is dialog already exists to prevent double loading */
if (container.length) {
return;
}
/* Create new container for dialog url */
var newContainer = $("<div></div>");
newContainer.attr("data-dialog-container", dialogOptions.url);
$("body").append(newContainer);
container = newContainer;
/* Load dialog into container */
$.post(dialogOptions.url, dialogOptions.data, function(response, status, xhr) {
if (status == "error") {
console.error("Couldn't load dialog " + dialogOptions.url +
" due to error: " + xhr.statusText);
return;
}
container.html(response);
var dialog = $('.modal', container);
dialog.modal('show');
/* Enable dialog result handlers */
dialog.on('hidden.bs.modal', function() {
if (dialog.data("dialog-result") != undefined) {
var dialogResultHandler = "on" + dialog.data("dialog-result");
if (dialogOptions[dialogResultHandler] !== undefined) {
dialogOptions[dialogResultHandler](dialog);
}
}
container.remove();
});
});
}
};
And the usage is:
DialogUtils.ShowDialog({
url: "@Url.Action("SubmitPaymentConfirmation")",
data: $("#SubmitPayment").serialize(),
onConfirm: function () {
$("#SubmitPayment").submit();
},
onConfirmAndPrint: function () {
$("#Print").val("true"); //some hidden field
$("#SubmitPayment").submit();
}
});
This function takes as a parameter dialogOptions
which contains the following properties:
url
: address of action which provides dialog HTMLdata
: parameter of actiononConfirm
,onConfirmAndPrint
– callbacks which are invoked when dialog is closed with specific state (for example:Confirm
,ConfirmAndPrint
, etc.)
For callbacks to work dialogs should be closed with specific state. By default, bootstrap doesn’t have any, so the wrapper function for modal.hide
would be required:
/* override original bootstrap modal function to set the dialog result on hide.
Usage: modal('hide', 'result') */
$(function () {
var originalModal = $.fn.modal;
$.fn.modal = function(option, result) {
if (option == 'hide' && typeof result == 'string') {
var $this = $(this);
$this.data("dialog-result", result);
arguments[1] = null;
}
originalModal.apply(this, arguments);
};
});
Now the dialog template should contain triggers which close dialog with specific state:
@model Dialogs.Models.SubmitPaymentConfirmation
@{
Layout = null;
}
<div class="modal fade">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close"
data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span></button>
<h4 class="modal-title">Payment Confirmation</h4>
</div>
<div class="modal-body">
<div class="row">
<label class="col-md-6 text-nowrap text-right">Amount:</label>
<span>@Html.DisplayFor(model => model.Amount)</span>
</div>
<div class="row">
<label class="col-md-6 text-nowrap text-right">Name On Card:</label>
<span>@Html.DisplayFor(model => model.NameOnCard)</span>
</div>
<div class="row">
<label class="col-md-6 text-nowrap text-right">CVV:</label>
<span>@Html.DisplayFor(model => model.CreditCardCvv2)</span>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default btn-primary"
onclick="$(this).closest('.modal').modal('hide', 'Confirm')">
<span class="glyphicon glyphicon-ok"></span> CONFIRM
</button>
<button type="button" class="btn btn-default"
onclick="$(this).closest('.modal').modal('hide', 'ConfirmAndPrint')">
<span class="glyphicon glyphicon-ok-circle"></span> CONFIRM AND PRINT
</button>
<button type="button" class="btn btn-default" data-dismiss="modal">
<span class="glyphicon glyphicon-remove-circle"></span> CANCEL
</button>
</div>
</div><!-- /.modal-content -->
</div><!-- /.modal-dialog -->
</div>
<!-- /.modal -->
You can see that Confirm
and ConfirmAndPrint
buttons contain handlers which close the dialog with specific state.
The last thing to say is dialog represents a separate action in the controller:
public ViewResult SubmitPaymentConfirmation(SubmitPaymentConfirmation paymentPageModel)
{
return View("SubmitPaymentConfirmation", paymentPageModel);
}
Explanation
For each dialog, a new container is created and attached to body. Dialog is loaded into container by url provided in the parameter. When dialog is closed, its close state is written to dialog-result
data field and callback with this state is executed. After that, container with dialog is removed. Dialog template is stored in a separate file and may contain scripts/styles assuming they do not correlate with page content.