jQuery Datatables 包装器






4.20/5 (6投票s)
为了简化使用 jQuery DataTables 的工作。
引言
jQuery DataTables 插件是一个优秀的客户端组件,可用于在 Web 浏览器中创建功能丰富的表格。该插件为放置在网页中的普通 HTML 表格添加了许多功能,例如过滤、分页、排序、更改页面长度等。但将其插件集成到 MVC 应用程序中需要一些努力。
假设您想在 DataTables 的某个页面上编辑、删除记录,并且在执行这些操作后,您想返回到同一页面。假设您还想从不同的数据源将不同的列放入 DataTable 中。
为了在 mvc 应用程序中实现这一点,您需要创建和处理“编辑”、“删除”按钮,记住当前页面、筛选字符串、排序的列,并从某个地方获取有关要放入 DataTable 中的列的信息。要完成所有这些操作,当然需要在 Java Script 和 C# 代码中付出一些努力。
本文以一个简单的 外资银行系统 为例,展示了如何简化该过程。
使用代码
这里是实现您在图片中看到的视图页面的代码。
@using BankRegistry.Models @using BankRegistry.Class @model RcBnk @{ ViewBag.Title = "Довідник іноземних банків"; } <h2>Перелік іноземних банків</h2> @using (Html.BeginForm("Create", "EditBank", new Position(ViewBag.cp), FormMethod.Get)) { if (((Infrastructure)ViewBag.cp).IsAdmin) { @* Html Helper to to generate add button *@ @Html.AddRecord(); } } @* Html Helper to to generate HTML Tag for Table tag for nessesary columns from table source *@ @(Html.DataTable<RcBnk, RcBnkMetaData>(ViewData)) <div style="width:300;"> <link href="~/Content/css/jquery.dataTables.min.css" rel="stylesheet" /> @section Scripts { <script src="~/Scripts/datatable_ext/table_init.js"></script> <script type="text/javascript"> $(document).ready(function () { @* Html Helper to to generate HTML java script code for call DataTables and make hundler for "edit" and "delete" buttons *@ @(BankRegistry.Class.DataTableHelper.DataTableInit<RcBnk, RcBnkMetaData>( ViewData, @* Infrastructure class *@ ViewBag.cp, @* Controler and action to load data from datasource *@ "/Banks/LoadTable", @* key field *@ "B010", @* Controler and action to edit current row *@ "/EditBank/EditBankRecord", @* Controler and action to delete current row *@ "/Banks/DeleteRecord", ((Infrastructure)ViewBag.cp).IsAdmin )) } ) </script> } </div>
为了标记要在 DataTable
中显示的列,我使用了用户属性 DataTableColumnAttribute
。
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, AllowMultiple = false)] sealed public class DataTableColumnAttribute : Attribute { public DataTableColumnAttribute(bool active, string name="") { } }
然后,我在模型中标记必要的列。
[MetadataType(typeof(RcBnkMetaData))] public partial class RcBnk { } public class RcBnkMetaData { [Key] [Display(Name = "Код")] [DataTableColumnAttribute(true)] public string B010 { get; set; } [Display(Name = "Країна")] [Required] [DataTableColumnAttribute(active: true, name: "K0401")] public string K040 { get; set; } [DataTableColumnAttribute(true)] public string SWIFT { get; set; } [Display(Name = "Назва")] [DataTableColumnAttribute(true)] public string Name { get; set; } [Display(Name = "Місцезнаходження")] [DataTableColumnAttribute(true)] public string Location { get; set; } [Display(Name = "Статус")] public int Status { get; set; } public int InQueue { get; set; } [Display(Name = "Користувач")] public int UserID { get; set; } [Display(Name = "Дата заведення")] [DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:MM/dd/yyyy}")] public System.DateTime EntryTime { get; set; } [Display(Name = "Файл імпорту")] public Nullable<int> ImpFile { get; set; } [Display(Name = "Файл експорту")] public Nullable<int> ExpFile { get; set; } [Display(Name = "Користувач, який останеній коригував")] [ReadOnly(true)] public Nullable<int> UpdUserID { get; set; } [Display(Name = "Дата останнього коригування")] [DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:MM/dd/yyyy}")] public Nullable<System.DateTime> LastUpdated { get; set; } public Nullable<int> CountryID { get; set; } }
这里是 Html.DataTable
和 DataTableInit
的代码。它们都从元数据中读取有关必要列的信息。因此,我可以将这些信息放在一个地方。
DataTable
public static IHtmlString DataTable<T,metatData>(this HtmlHelper helper, ViewDataDictionary<T> Model) { TagBuilder table = new TagBuilder("table id=\"tblGreed\" class=\"table table-striped table-bordered\" cellspacing=\"0\" data-page-length='10'"); TagBuilder tableThead = new TagBuilder("thead"); TagBuilder tableTr = new TagBuilder("tr"); var type = typeof(metatData); TagBuilder tableTh; foreach (var property in Model.ModelMetadata.Properties) { var memInfo = type.GetMember(property.PropertyName); if (memInfo.Length == 0) continue; var attributes = memInfo[0].GetCustomAttributes(typeof(BankRegistry.Controllers.DataTableColumnAttribute), true); if (attributes.Count() > 0) { var attributeName = memInfo[0].GetCustomAttributes(typeof(System.ComponentModel.DataAnnotations.DisplayAttribute), true); string colname = attributeName.Length > 0 ? ((System.ComponentModel.DataAnnotations.DisplayAttribute)attributeName[0]).Name : property.PropertyName; tableTh = new TagBuilder("th"); tableTh.InnerHtml = colname; tableTr.InnerHtml += tableTh; } } tableTh = new TagBuilder("th"); tableTr.InnerHtml += tableTh; tableThead.InnerHtml += tableTr; table.InnerHtml += tableThead; return new HtmlString(table.ToString()); }
DataTableInit
public static IHtmlString DataTableInit<T,metaData> (ViewDataDictionary<T> Model, Infrastructure cp, string LoadTable="", string KeyColumn="", string EditUrl="", string DeleteUrl = "", bool FullAccess = true ) { System.Text.StringBuilder sb = new System.Text.StringBuilder(); sb.Append("var ColumnsArray = new Array;"); var type = typeof(metaData); foreach (var property in Model.ModelMetadata.Properties) { var memInfo = type.GetMember(property.PropertyName); if (memInfo.Length == 0) continue; var attributes = memInfo[0].GetCustomAttributes(typeof(BankRegistry.Controllers.DataTableColumnAttribute), true); if (attributes.Count() > 0) { sb.Append("ColumnsArray.push({data: \"" + property.PropertyName + "\", autoWidth: true});"); sb.Append(Environment.NewLine); } } if (FullAccess) sb.Append("ColumnsArray.push({data:\"\", width: \"20%\", orderable: false});"); else sb.Append("ColumnsArray.push({data:\"\", width: \"10%\", orderable: false});"); sb.Append(Environment.NewLine); sb.Append("var CurrentPage=" + cp.currentPage + ";"); sb.Append(Environment.NewLine); sb.Append("var Sorting=" + cp.sorting + ";"); sb.Append(Environment.NewLine); sb.Append("var Filter='" + cp.filter + "'" + ";"); sb.Append(Environment.NewLine); sb.Append("var FullAccess='" + FullAccess + "'" + ";"); sb.Append(Environment.NewLine); sb.Append("var table = DataTable(ColumnsArray, '" + LoadTable + "', CurrentPage, Sorting, Filter, FullAccess)" + ";"); string editclick = "$('#tblGreed tbody').on('click', '#edit', function () {"+ "var data = table.row($(this).parents('tr')).data();"+ "$(location).attr('href', '" + EditUrl + "?id=' + data['" + KeyColumn + "']" + "+ '&pageNumber=' + table.page.info().page"+ "+ '&filter=' + $('div.dataTables_filter input').val()"+ "+ '&sorting=' + table.order()[0][0]);});"; sb.Append(editclick); string deleteclick = "$('#tblGreed tbody').on('click', '#delete', function () {"+ "var conf = confirm('Вилучити запис ?');"+ "if (conf==true)"+ "{"+ "var data = table.row($(this).parents('tr')).data();"+ "$(location).attr('href', '" + DeleteUrl + "?id=' + data['" + KeyColumn + "']" + "+ '&pageNumber=' + table.page.info().page"+ "+ '&filter=' + $('div.dataTables_filter input').val()"+ "+ '&sorting=' + table.order()[0][0]);"+ "}})"; sb.Append(deleteclick); return new HtmlString(sb.ToString()); }
这里是 Jquery DataTable 模式的 Java Script 代码。这里有保存页面当前位置、筛选器、管理员标志所需的基础设施的必要参数。
function DataTable( ColumnsArray, // Array of columns to show LoadTable, // Url of mvc code to load date CurrentPage, // Int number of current page Sorting, // int number of column by with DataTable is sorted Filter, // string filter by with DataTable is filtered FullAccess // sign of full access to show update buttons ) { var texteditbutton = 'Коригувати' var deletetag = "<button id='delete' type='button' class='btn btn-default'>Вилучити</button>" if (FullAccess != 'True') { texteditbutton = 'Переглянути' deletetag = '' } var table = $('#tblGreed').DataTable({ "lengthMenu": [[5, 10, 25, 50, -1], [5, 10, 25, 50, "Всі"]], iDisplayLength: -1, initComplete: function () { table.search(Filter).draw(); table.page(CurrentPage).draw(false); }, searching: true, ordering: true, order: [[Sorting, "desc"]], "bInfo": false, 'bLengthChange': true, oLanguage: { oPaginate: { sNext: "Вперед", sPrevious: "Назад", sFirst: "Початок", sLast: "Кінець", }, sLengthMenu: "Відображати _MENU_", sSearch: "Пошук: " }, ajax: { url: LoadTable, contentType: "application/json" }, columns: ColumnsArray, columnDefs: [{ "targets": -1, "data": null, "defaultContent": "<div class='btn-group'>" + "<button id='edit' type='button' class='btn btn-default'>" + texteditbutton + "</button><span> </span>" + deletetag }] }); $('#tblGreed thead th').each(function () { var title = $(this).text(); $(this).html('<input type="text" placeholder="Пошук ' + title + '" />'); }); table.columns().eq(0).each(function (colIdx) { $('input', table.column(colIdx).header()).on('keyup change', function () { table .column(colIdx) .search(this.value) .draw(); }); }) return table; }
这里是 MVC 操作中的代码,用于将数据加载到 DataTable 中。这里,有关列的信息也从模型元数据中读取。
[HttpGet] //[OutputCache(Duration=50, VaryByParam="none")] public ActionResult LoadTable() { var names = typeof(RcBnk).GetProperties() .Select(property => property.Name) .ToArray(); var type = typeof(RcBnkMetaData); StringBuilder sb = new StringBuilder("new ("); foreach (string property in names) { var memInfo = type.GetMember(property); if (memInfo.Length == 0) continue; var attributes = memInfo[0].GetCustomAttributes(typeof(BankRegistry.Controllers.<code>DataTableColumnAttribute</code>), true); if (attributes.Length == 0) continue; if (attributes.Count() > 0) { string sbstring; if (property == "K040") sbstring = "K0401.TXT as K040"; else sbstring = property; sb.Append(sbstring + ","); } } sb.Append(")"); string select = sb.ToString(); select = select.Remove(select.LastIndexOf(','),1); var jsonData = new { data = _db.Banks.All.Where(x => x.Status == 0).OrderBy(r => r.Name). Select(select) }; return Json(jsonData, JsonRequestBehavior.AllowGet); }
摘要
通过这种方式,您可以处理 MVC 应用程序中的任何其他数据源。您需要做的就是通过属性标记必要的列,并在控制器中编写用于更新数据的操作。使用实体框架,这非常简单。