اصول نمایش اطلاعات مودال به کمک bootstrap در مطلب «
استفاده از modal dialogs مجموعه Twitter Bootstrap برای گرفتن تائید از کاربر» بررسی شدند.
در این قسمت قصد داریم یک فرم Ajaxایی را در ASP.NET MVC به همراه تمام مسایل اعتبارسنجی، پردازش اطلاعات و غیره را به کمک Twitter Bootstrap و jQuery Ajax پیاده سازی کنیم.
تهیه افزونه jquery.bootstrap-modal-ajax-form.js
از این جهت که مباحث مرتبط با نمایش و پردازش فرمهای مودال Ajaxایی به کمک Twitter Bootstrap اندکی نکته دار و طولانی هستند، بهتر است این موارد را به شکل یک افزونه، کپسوله کنیم. کدهای کامل افزونه jquery.bootstrap-modal-ajax-form.js را در ادامه ملاحظه میکنید:
// <![CDATA[
(function ($) {
$.bootstrapModalAjaxForm = function (options) {
var defaults = {
renderModalPartialViewUrl: null,
renderModalPartialViewData: null,
postUrl: '/',
loginUrl: '/login',
beforePostHandler: null,
completeHandler: null,
errorHandler: null
};
var options = $.extend(defaults, options);
var validateForm = function (form) {
//فعال سازی دستی اعتبار سنجی جیکوئری
var val = form.validate();
val.form();
return val.valid();
};
var enableBootstrapStyleValidation = function () {
$.validator.setDefaults({
highlight: function (element, errorClass, validClass) {
if (element.type === 'radio') {
this.findByName(element.name).addClass(errorClass).removeClass(validClass);
} else {
$(element).addClass(errorClass).removeClass(validClass);
$(element).closest('.control-group').removeClass('success').addClass('error');
}
$(element).trigger('highlited');
},
unhighlight: function (element, errorClass, validClass) {
if (element.type === 'radio') {
this.findByName(element.name).removeClass(errorClass).addClass(validClass);
} else {
$(element).removeClass(errorClass).addClass(validClass);
$(element).closest('.control-group').removeClass('error').addClass('success');
}
$(element).trigger('unhighlited');
}
});
}
var enablePostbackValidation = function () {
$('form').each(function () {
$(this).find('div.control-group').each(function () {
if ($(this).find('span.field-validation-error').length > 0) {
$(this).addClass('error');
}
});
});
}
var processAjaxForm = function (dialog) {
$('form', dialog).submit(function (e) {
e.preventDefault();
if (!validateForm($(this))) {
//اگر فرم اعتبار سنجی نشده، اطلاعات آن ارسال نشود
return false;
}
//در اینجا میتوان مثلا دکمهای را غیرفعال کرد
if (options.beforePostHandler)
options.beforePostHandler();
//اطلاعات نباید کش شوند
$.ajaxSetup({ cache: false });
$.ajax({
url: options.postUrl,
type: "POST",
data: $(this).serialize(),
success: function (result) {
if (result.success) {
$('#dialogDiv').modal('hide');
if (options.completeHandler)
options.completeHandler();
} else {
$('#dialogContent').html(result);
if (options.errorHandler)
options.errorHandler();
}
}
});
return false;
});
};
var mainContainer = "<div id='dialogDiv' class='modal hide fade in'><div id='dialogContent'></div></div>";
enableBootstrapStyleValidation(); //اعمال نکات خاص بوت استرپ جهت اعتبارسنجی یکپارچه با آن
$.ajaxSetup({ cache: false });
$.ajax({
type: "POST",
url: options.renderModalPartialViewUrl,
data: options.renderModalPartialViewData,
contentType: "application/json; charset=utf-8",
dataType: "json",
complete: function (xhr, status) {
var data = xhr.responseText;
var data = xhr.responseText;
if (xhr.status == 403) {
window.location = options.loginUrl; //در حالت لاگین نبودن شخص اجرا میشود
}
else if (status === 'error' || !data) {
if (options.errorHandler)
options.errorHandler();
}
else {
var dialogContainer = "#dialogDiv";
$(dialogContainer).remove();
$(mainContainer).appendTo('body');
$('#dialogContent').html(data); // دریافت پویای اطلاعات مودال دیالوگ
$.validator.unobtrusive.parse("#dialogContent"); // فعال سازی اعتبارسنجی فرمی که با ایجکس بارگذاری شده
enablePostbackValidation();
// و سپس نمایش آن به صورت مودال
$('#dialogDiv').modal({
backdrop: 'static', //با کلیک کاربر روی صفحه، صفحه مودال بسته نمیشود
keyboard: true
}, 'show');
// تحت نظر قرار دادن این فرم اضافه شده
processAjaxForm('#dialogContent');
}
}
});
};
})(jQuery);
// ]]>
توضیحات:
- توابع enableBootstrapStyleValidation و enablePostbackValidation در مطلب «
اعمال کلاسهای ویژه اعتبارسنجی Twitter bootstrap به فرمهای ASP.NET MVC» بررسی شدند.
- این افزونه با توجه به مقدار renderModalPartialViewUrl، یک partial view را از برنامه ASP.NET MVC درخواست میکند.
- سپس این partial view را به صورت خودکار به صفحه اضافه کرده و آنرا به صورت modal نمایش میدهد.
- پس از افزودن فرم Ajaxایی دریافتی، مسایل اعتبارسنجی را به آن اعمال کرده و سپس دکمه submit آنرا تحت کنترل قرار میدهد.
- در زمان submit، ابتدا بررسی میکند که آیا فرم معتبر است و اعتبارسنجی آن بدون مشکل است؟ اگر اینچنین است، اطلاعات فرم را به آدرس postUrl به صورت Ajaxایی ارسال میکند.
کدهای مدل برنامهusing System.ComponentModel;
using System.ComponentModel.DataAnnotations;
namespace Mvc4TwitterBootStrapTest.Models
{
public class User
{
public int Id { set; get; }
[DisplayName("نام")]
[Required(ErrorMessage="لطفا نام را تکمیل کنید")]
public string Name { set; get; }
[DisplayName("نام خانوادگی")]
[Required(ErrorMessage = "لطفا نام خانوادگی را تکمیل کنید")]
public string LastName { set; get; }
}
}
در اینجا یک مدل سادهرا به همراه ویژگیهای اعتبارسنجی و نامهای نمایشی خواص ملاحظه میکنید.
کدهای کنترلر برنامهusing System.Web.Mvc;
using Mvc4TwitterBootStrapTest.Models;
namespace Mvc4TwitterBootStrapTest.Controllers
{
public class ModalFormAjaxController : Controller
{
[HttpGet]
public ActionResult Index()
{
return View(); //نمایش صفحه اولیه
}
[HttpPost] //برای این حالت امنتر است
//[AjaxOnly]
public ActionResult RenderModalPartialView()
{
//رندر پارشال ویوو صفحه مودال به همراه اطلاعات مورد نیاز آن
return PartialView(viewName: "_ModalPartialView", model: new User { Name = "", LastName = "" });
}
[HttpPost]
//[AjaxOnly]
public ActionResult Index(User user) //ذخیره سازی اطلاعات
{
if (this.ModelState.IsValid)
{
//todo: SaveChanges;
return Json(new { success = true });
}
this.ModelState.AddModelError("", "خطایی رخ داده است");
return PartialView("_ModalPartialView", user);
}
}
}
کدهای کنترلر برنامه در این حالت از سه قسمت تشکیل میشود:
الف) متد Index حالت HttpGet که صفحه ابتدایی را نمایش خواهد داد.
ب) متد RenderModalPartialView یک partial view اضافه شده به برنامه به نام _ModalPartialView.cshtml را بازگشت میدهد. این partial view در حقیقت همان فرمی است که قرار است به صورت مودال نمایش داده شود و پردازش آن نیز Ajaxایی باشد.
ج) متد Index حالت HttpPost که نهایتا اطلاعات فرم مودال را دریافت خواهد کرد. اگر پردازش موفقیت آمیز بود، نیاز است همانند کدهای فوق return Json صورت گیرد. در غیراینصورت مجددا همان partial view را بازگشت دهید.
کدهای Index.cshtml@{
ViewBag.Title = "Index";
var renderModalPartialViewUrl = Url.Action("RenderModalPartialView", "ModalFormAjax");
var postDataUrl = Url.Action("Index", "ModalFormAjax");
}
<h2>
Index</h2>
<a href="#" class="btn btn-primary" id="btnCreate">ثبت اطلاعات</a>
@section JavaScript
{
<script type="text/javascript">
$(function () {
$('#btnCreate').click(function (e) {
e.preventDefault(); //میخواهیم لینک به صورت معمول عمل نکند
$.bootstrapModalAjaxForm({
postUrl: '@postDataUrl',
renderModalPartialViewUrl: '@renderModalPartialViewUrl',
renderModalPartialViewData: {},
loginUrl: '/login',
beforePostHandler: function () {
},
completeHandler: function () {
// Refresh: برای حالتیکه نیاز به به روز رسانی کامل صفحه زیرین باشد
// location.reload();
},
errorHandler: function () {
}
});
});
});
</script>
}
این کدها متناظر هستند با کدهای view اکشن متد Index در حالت Get.
- در اینجا یک لینک ساده در صفحه قرار گرفته و به کمک کلاس btn مجموعه bootstrap به شکل یک دکمه مزین شده است.
- در ادامه نحوه استفاده از افزونهای را که در ابتدای بحث طراحی کردیم، ملاحظه میکنید. کار با آن بسیار ساده است و تنها باید مسیرهای ارسال اطلاعات نهایی به سرور یا postDataUrl و مسیر دریافت partial view رندر شده یا renderModalPartialViewUrl به آن معرفی شود. سایر مسایل آن خودکار است.
کدهای _ModalPartialView.cshtml یا همان فرم مودال برنامه@model Mvc4TwitterBootStrapTest.Models.User
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">
×</button>
<h5>
افزودن کاربر جدید</h5>
</div>
@using (Html.BeginForm("Index", " ModalFormAjax", FormMethod.Post, new { @class = "modal-form" }))
{
<div class="modal-body">
@Html.ValidationSummary(true, null, new { @class = "alert alert-error alert-block" })
<fieldset class="form-horizontal">
<legend>مشخصات کاربر</legend>
<div class="control-group">
@Html.LabelFor(model => model.Name, new { @class = "control-label" })
<div class="controls">
@Html.EditorFor(model => model.Name)
@Html.ValidationMessageFor(model => model.Name, null, new { @class = "help-inline" })
</div>
</div>
<div class="control-group">
@Html.LabelFor(model => model.LastName, new { @class = "control-label" })
<div class="controls">
@Html.EditorFor(model => model.LastName)
@Html.ValidationMessageFor(model => model.LastName, null, new { @class = "help-inline" })
</div>
</div>
</fieldset>
</div>
<div class="modal-footer">
<button class="btn btn-primary" type="submit">
ارسال</button>
<button class="btn" data-dismiss="modal" aria-hidden="true">
انصراف</button>
</div>
}
در اینجا
اطلاعات فرمی را ملاحظه میکنید که قرار است به صورت مودال نمایش داده شود. نحوه طراحی آن بر اساس
نکات form-horizontal است. همچنین divهای modal-header، modal-body و modal-footer نیز به این فرم ویژه اضافه شدهاند تا به خوبی توسط bootstrap پردازش گردد.
حاصل نهایی این مبحث را در دو شکل ذیل ملاحظه میکنید. صفحه index نمایش دهنده یک دکمه و در ادامه باز شدن یک فرم مودال، پس از کلیک بر روی دکمه ثبت اطلاعات.