使用 AJAX 在 ASP.NET MVC 中刷新表格内容 (jQuery DataTables 和 ASP.NET MVC 集成 - 第三部分)






4.92/5 (42投票s)
如何在 ASP.NET MVC 中使用 jQuery DataTables 插件刷新表格内容
目录
简介
在本文中,我将展示如何通过 AJAX 刷新 HTML 表格内容。如果您使用的是普通的 HTML 表格,重新加载表格并不是一项非常复杂的任务。您所要做的就是向服务器端页面发送一个 AJAX 请求,获取服务器的响应,然后将其放入表格中。我相信您已经做过很多次了。有一个简单的 jQuery 代码可以做到这一点。
$("table#employees tbody").load("TableContent.aspx");
此调用将向服务器端页面 TableContent.aspx 发送一个 AJAX 调用,读取 TableContent.aspx 提供的响应,并将其放入表格的 body 中。在 TableContent.aspx 页面中,您需要返回一个有效的 HTML,代表将放置在表格中的行集。
如果您的表格很简单,可以替换为服务器响应的内容,那么这 funziona 良好。但是,如果您有一些高级功能,例如分页、排序、过滤,事情可能会变得更加复杂。当您向服务器发送请求时,您需要包含有关当前页面和表格状态的信息,并确保您已加载了正确的内容,选择了分页中的正确页码等。如果您有更高级的表格,最好使用一些已经内置了刷新功能的现有组件。
我的选择是 jQuery DataTables 插件。使用 jQuery DataTables 插件,您只需一行 JavaScript 代码即可为普通表格添加分页、过滤和排序功能。
var oEmployeesTable = $('table#employees').dataTable();
本示例使用了一个 ID 为“employees
”的普通 HTML 表格,并将 DataTables 插件应用于该表格。此调用将为表格添加分页、排序和过滤功能。
您也可以使用略有不同的调用轻松创建一个完全 AJAX 化的表格。
var oEmployeesTable = $('table#employees').dataTable({
"bServerSide": true,
"sAjaxSource": "DataContent.aspx"
});
在这种情况下,设置了两个参数,指定信息将从服务器端页面 DataContent.aspx 而非 HTML 中获取。
如果您使用 DataTables 来刷新表格内容,您将需要执行一行 JavaScript 代码。
oEmployeesTable.fnDraw();
此调用将刷新表格内容。在本文中,我将展示如何在 ASP.NET MVC 应用程序中实现刷新功能。
背景
jQuery DataTables 插件是一个优秀的 jQuery 库,它使您能够以最少的精力创建完全 AJAX 化的表格。要使用 jQuery DataTables 插件创建 AJAX 化的表格,您需要实现以下元素:
- 在页面的 HTML 中放置一个空的表格。这个空的表格将定义表格的结构(例如,列、样式等)。表格应只在
THEAD
元素中有一个标题,一个空的 body,以及一个可选的TFOOT
元素。表格中的行不是必需的,因为它们将通过 AJAX 调用加载。 - 创建一个服务器端页面,当通过 AJAX 调用时,该页面将为表格提供行。在本文中,将实现一个 ASP.NET MVC 控制器,它将为表格提供数据行。
- 初始化 jQuery DataTables 插件以从控制器加载表格内容。
结果是,您将获得一个完全 AJAX 化的表格,其中 jQuery DataTables 已自动添加了分页、按表头排序和按关键字过滤功能,而不是一个空表格。表格的示例显示在下图。
如您所见,jQuery DataTables 插件采用了一个没有内容的普通表格,通过 AJAX 调用填充了行,并添加了排序、过滤和分页的元素。在接下来的部分中,您将看到只需几行 JavaScript 代码即可初始化此表格,并将其转换为功能齐全的 AJAX ized 表格。
您可以在 ** jQuery DataTables 和 ASP.NET MVC 集成 - 第一部分** 文章中找到关于将 jQuery DataTables 插件与 ASP.NET MVC 控制器集成的详细说明。
一旦您实现了控制器并初始化了 jQuery DataTables 插件,它将处理与用户的完整交互。每次用户更改表格的状态时(例如,使用分页更改页面,按列对行排序,或执行搜索),DataTables 插件都会将信息发送到控制器并刷新表格的内容。
然而,在某些情况下,您需要手动刷新表格内容。刷新表格内容是许多应用程序中的常见需求——一些示例如下:
- 您可能想添加一个 **刷新** 按钮,允许用户刷新表格中显示的数据。
- 您可能想实现表格内容的某种周期性刷新,以便为用户提供最新的数据(例如,某些实时比分实现)。
- 您可能想实现某种 AJAX 化的搜索,用户在表单中输入搜索条件,您想在不刷新整个页面的情况下刷新表格中的数据。
- 您可能想添加一个主表格或下拉列表,当用户在表格或下拉列表中选择某个值时,您可能想刷新依赖的表格。
- 您可能想为表格添加某种过滤器,用户将在其中输入一些文本或在下拉列表中选择某个值,因此您需要刷新表格内容以匹配过滤器。
要实现这些场景,您需要刷新 DataTables 内容。本文的目标是展示如何使用 jQuery DataTables 插件提供的 API 来做到这一点。
这是系列文章的第三篇,解释了 jQuery DataTables 插件如何在 ASP.NET MVC Web 应用程序中集成。如果您不熟悉 DataTables 插件与 ASP.NET MVC 服务器端代码的集成,您可能想在继续之前阅读本系列中的第一篇文章。
使用代码
为了说明起见,我们将使用一个简单的 ASP.NET MVC Web 应用程序来列出员工。您需要做的第一件事是创建一个标准的 ASP.NET 模型-视图-控制器结构。此设置需要三个步骤:
- 创建代表要显示的数据结构的 Model 类。
- 创建将响应用户事件的 Controller 类。
- 创建将渲染数据并创建发送到浏览器窗口的 HTML 代码的 View。
此外,您还需要在项目中包含一些 JavaScript 组件。需要下载以下 JavaScript 组件:
- jQuery 库 v1.4.4,包含 DataTables 插件使用的标准类。
- jQuery DataTables 插件 v1.7.5,包括用于在页面上应用默认样式的可选 DataTables CSS 样式表。
这些文件应存储在本地文件系统中,并包含在客户端渲染的 HTML 页面中。下面将解释这些文件的用法示例。
模型
示例中需要添加两个包含公司和员工信息的类。这些类显示在以下列表中:
public class Company
{
public int ID { get; set; }
public string Name { get; set; }
public string Address { get; set; }
public string Town { get; set; }
}
public class Employee
{
public int EmployeeID { get; set; }
public string Name { get; set; }
public string Position { get; set; }
public int CompanyID { get; set; }
}
员工通过 CompanyID
属性与公司相关联。这些类将用于在页面上显示信息。
视图
View 用于在服务器端渲染数据并将 HTML 代码发送到浏览器。有一个布局页面,用于包含页面上使用的所有必需的 CSS 和 JavaScript 文件。该布局页面如下所示:
<!DOCTYPE html>
<html>
<head>
<title>Refreshing table content using a JQuery DataTables plugin</title>
<link href="@Url.Content("~/Content/dataTables/demo_page.css")"
rel="stylesheet" type="text/css" />
<link href="@Url.Content("~/Content/dataTables/demo_table.css")"
rel="stylesheet" type="text/css" />
<link href="@Url.Content("~/Content/dataTables/demo_table_jui.css")"
rel="stylesheet" type="text/css" />
<link href="@Url.Content("~/Content/themes/base/jquery-ui.css")"
rel="stylesheet" type="text/css" media="all" />
<link href="@Url.Content("~/Content/themes/smoothness/jquery-ui-1.7.2.custom.css")"
rel="stylesheet" type="text/css" media="all" />
<script src="@Url.Content("~/Scripts/jquery-1.4.4.min.js")"
type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.dataTables.min.js")"
type="text/javascript"></script>
@RenderSection("head", required: false)
</head>
<body id="dt_example">
<div id="container">
@RenderBody()
</div>
</body>
</html>
布局页面有两个可以填充的区域:
head
区域,页面的 JavaScript 调用将在此处注入。body
区域,允许使用此布局页面的页面向要在页面上显示的页面注入代码。
在接下来的部分中,我将展示几个使用此布局页面并刷新表格内容的页面实现。
案例 1 - 添加“刷新”按钮
在第一个示例中,我将展示如何添加一个 **刷新** 按钮,当用户按下该按钮时,它将重新加载表格的内容。下图显示了一个示例:
如上所述,我们需要一个包含表格数据的空表格和一个刷新按钮。页面的 body 显示在以下列表中:
<button id="Refresh" type="button">Refresh<button/>
<table id="employees" class="display">
<thead>
<tr>
<th>ID</th>
<th>Employee</th>
<th>Position</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
准备好静态 HTML 后,我们需要初始化 DataTables 插件,并为刷新按钮附加一个点击处理程序,该处理程序将重绘表格。代码示例显示在以下列表中。
@section head{
<script language="javascript" type="text/javascript">
$(document).ready(function () {
var oEmployeesTable = $('#employees').dataTable({
"bJQueryUI": true,
"bServerSide": true,
"sAjaxSource": "MasterDetailsAjaxHandler"
});
$("#Refresh").click(function (e) {
oEmployeesTable.fnDraw();
});
});
</script>
}
这段代码应该放在视图的 head
部分。文档就绪函数中的第一条语句将 DataTables
插件应用于 employees
表格,指定它将以服务器端模式工作(这意味着在每次用户操作时,插件都会要求服务器端页面提供应显示的新数据),定义通过 AJAX 调用调用的 URL 是 MasterDetailsAjaxHandler
- 这是提供表格内容的控制器路径。bJQueryUI
标志不是强制性的——它仅用于将 jQuery UI 样式应用于表格。
当表格初始化时,代码中会添加一个刷新按钮的点击处理程序,该处理程序将绘制表格的内容。每次调用 draw 时,DataTables
插件将再次调用服务器端页面,并获取将加载到表格 body 中的新数据集。
提供内容的控制器在控制器部分进行了描述。
案例 2 - 定期刷新表格内容
如果您不想强制用户刷新表格,可以添加一个函数,该函数将定期调用以刷新表格。代码与案例 1 中显示的代码非常相似。唯一的区别是不需要刷新按钮,并且使用了一个 set interval 函数而不是 click handler,如下面的列表所示:
@section head{
<script language="javascript" type="text/javascript">
var oEmployeesTable = null;
function refresh() {
if (oEmployeesTable != null)
oEmployeesTable.fnDraw();
}
setInterval("refresh()", 1000);
$(document).ready(function () {
oEmployeesTable = $('#employees').dataTable({
"bJQueryUI": true,
"bServerSide": true,
"sAjaxSource": "/Home/MasterDetailsAjaxHandler"
});
});
</script>
}
在全局作用域中定义了对 employees
表格、刷新表格的函数以及每秒调用刷新函数的计时器的引用。然后在文档就绪处理程序中,使用 DataTables
插件初始化 employees
表格,并设置全局引用。
结果是,此表格将每秒自动重新加载一次。发送到服务器的 AJAX 调用的跟踪显示在下图中:
请注意,对 employees
表格、函数和 interval 调用的引用被放置在全局作用域中,而不是放在文档就绪处理程序的 body 中,因为这些函数引用将在文档就绪处理程序完成时丢失。
案例 3 - 选择父行时刷新表格内容
在此示例中,我将展示当在主表中选择一个公司时,如何刷新从表(employees
)的内容。在这种情况下,我们将有两个表格——一个包含公司列表的父表格和一个包含员工列表的子表格。下图显示了那种页面的示例:
当用户在主表中选择公司时,子表中将显示属于该公司的员工。页面的 body 显示在以下列表中:
<div id="demo">
<table id="companies" class="display">
<thead>
<tr>
<th>Company name</th>
<th>Address</th>
<th>Town</th>
</tr>
</thead>
<tbody>
<tr id="0" class="masterlink">
<td>Emkay Entertainments</td>
<td>Nobel House, Regent Centre</td>
<td>Lothian</td>
</tr>
<tr id="1" class="masterlink">
<td>The Empire</td>
<td>Milton Keynes Leisure Plaza</td>
<td>Buckinghamshire</td>
</tr>
<tr id="2" class="masterlink">
<td>Asadul Ltd</td>
<td>Hophouse</td>
<td>Essex</td>
</tr>
<tr id="3" class="masterlink">
<td>Ashley Mark Publishing Company</td>
<td>1-2 Vance Court</td>
<td>Tyne & Wear</td>
</tr>
<tr id="4" class="masterlink">
<td>MuchMoreMusic Studios</td>
<td>Unit 29</td>
<td>London</td>
</tr>
<tr id="5" class="masterlink">
<td>Audio Records Studios</td>
<td>Oxford Street</td>
<td>London</td>
</tr>
</tbody>
</table>
<table id="employees" class="display">
<thead>
<tr>
<th>ID</th>
<th>Employee</th>
<th>Position</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
</div>
包含公司的第一个表格包含五个公司的列表,而 employees
表格是空的。employees
表格将通过 AJAX JavaScript 调用填充。companies
表格中的每一行都包含公司的 ID——此信息将用于加载所选公司的 employees
。
head
部分包含初始化并连接这两个表格的 JavaScript 代码。JavaScript 初始化代码显示在以下列表中:
<script language="javascript" type="text/javascript">
$(document).ready(function () {
/* Initialize master table - optionally */
var oCompaniesTable = $('#companies').dataTable({ "bJQueryUI": true });
/* Highlight selected row - optionally */
$("#companies tbody").click(function (event) {
$(oCompaniesTable.fnSettings().aoData).each(function () {
$(this.nTr).removeClass('row_selected');
});
$(event.target.parentNode).addClass('row_selected');
});
var MasterRecordID = null;
var oEmployeesTable = $('#employees').dataTable({
"sScrollY": "100px",
"bJQueryUI": true,
"bServerSide": true,
"sAjaxSource": "MasterDetailsAjaxHandler",
"bProcessing": true,
"fnServerData": function (sSource, aoData, fnCallback) {
aoData.push({ "name": "CompanyID", "value": MasterRecordID });
$.getJSON(sSource, aoData, function (json) {
fnCallback(json)
});
}
});
$(".masterlink").click(function (e) {
MasterRecordID = $(this).attr("id");
oEmployeesTable.fnDraw();
});
});
</script>
前两个语句是可选的。第一个语句使用 jQuery DataTables 插件初始化公司表格,以便添加分页、过滤和排序功能(这对于表格之间的父子关系不是必需的,因为父表格可以是一个普通表格)。第二个语句在选定的父表格行上添加 row_selected
类。这也不是必需的,但它有助于突出显示其 employees
显示在子表格中的公司。
本地变量 MasterRecordID
用于保存当前选定公司的 ID。第四条语句初始化子 employees
表格。大多数设置是可选的,并且不影响父子配置,因为初始化中唯一相关的语句是:
- 使用
bServerSide
和sAjaxSource
参数实现的服务器端处理配置。 fnServerData
方法用于将选定公司的 ID 注入到发送到服务器端的 AJAX 调用中。此方法用于将一个名为CompanyID
的附加参数以及MasterRecordID
变量的值添加到发送到服务器端的 AJAX 调用中。
最后一条语句附加了事件处理程序,该处理程序填充选定行的 ID,并在每次单击父表格中的行时强制重绘子表格。重绘表格会向服务器端发送 AJAX 请求,并使用属于所选 company
的 employee
记录更新表格。
案例 4 - 表单提交时刷新表格
当您需要重新加载表格时,一个常见的场景是您通过 AJAX 提交一些表单内容,并且您想重新加载表格以刷新行。例如,您可能在页面上添加一个添加表单,当成功添加新项目时,您可能想重新加载表格内容。下图显示了那种页面的示例。
为了创建这种功能,我们需要在视图中添加一个按钮和一个对话框。视图 body 看起来像以下 HTML 代码:
<div id="dialog" title="Add new item">
<label for="name">Title</label>
<input type="text" id="name" name="name" value="" />
<button type="button" id="save">Save</button>
</div>
<button id="add">Add</button>
<table id="employees" class="display">
<thead>
<tr>
<th>ID</th>
<th>Employee</th>
<th>Position</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
HTML 中添加了一个对话框,其中包含用于新项目的文本输入和一个 **保存** 按钮。此外,一个用于打开对话框的按钮被添加到表格上方。已使用 DataTables
插件增强的表格与前面的案例相同。
现在,我们需要在 **保存** 按钮向服务器端提交请求后刷新表格。在这种情况下,我们需要在 AJAX 调用的 success handler 中调用 fnDraw
函数。这种 JavaScript 代码的示例显示在以下列表中:
var oEmployeesTable = $('#employees').dataTable({
"bJQueryUI": true,
"bServerSide": true,
"sAjaxSource": "/Home/MasterDetailsAjaxHandler"
});
$("#dialog").dialog({ autoOpen: false });
$("#add").click(function (e) {
$("#dialog").dialog("open");
});
$("#save").click(function (e) {
e.preventDefault();
e.stopPropagation();
$.ajax({
url: "/Home/AddItem",
data: {
name: function(){$("#name").val();}
},
success: function () {
$("#dialog").dialog("close");
oEmployeesTable.fnDraw();
}
});
});
第一部分是标准的 DataTable
初始化,与前面的示例相同。然后初始化对话框(它不会自动打开),在 **添加** 按钮上添加一个打开对话框的处理程序,并在 **保存** 按钮上添加一个提交 AJAX 请求到服务器端页面并发送输入的名称的处理程序。在 AJAX 调用的 success handler 中,关闭对话框并重绘表格。
结果是,每次提交表单时,您都会看到表格被重新加载。
案例 5 - 使用表单元素进行过滤
其他用例的实现与上述三种方法类似。您可以轻松添加一些下拉选择框、复选框,甚至是整个表单来刷新表格内容。
您需要做的就是附加一个事件处理程序,该处理程序将调用 fnDraw
函数,并将您想要通过 AJAX 调用发送到控制器的参数注入到初始化中的 fnServerData
设置中。当调用 fnDraw
时,DataTables
插件将发送一个新的 AJAX 请求,传递 fnServerData
中定义的参数,接受结果,并将它们放入表格。因此,我不会展示其他用例的实现,因为它们非常相似。
如果您想使用直接与表格列相关的表单元素进行刷新,有一个更简单的选项。您可以使用 jQuery DataTables ColumnFilter 附加组件,它可以为 DataTable
添加表单过滤器。如果您在列中或在单独的表单中添加过滤器,您可以看到这个表单过滤器是如何工作的。此过滤器可以应用于表格中已有的行数据,也可以应用于 AJAX 化的表格。使用此插件,您无需实现事件处理程序和 AJAX 请求。您需要做的就是将列过滤器插件应用于服务器端模式配置的 DataTables 插件。以下列表显示了初始化 columnfilter
插件与 DataTables 在服务器端处理模式下的代码示例:
$('#employees').dataTable({
"bJQueryUI": true,
"bServerSide": true,
"sAjaxSource": "MasterDetailsAjaxHandler"
}).columnFilter({
aoColumns: [ { type: "select"},
{ type: "text" },
{ type: "text" },
{ type: "text" }
]
});
此示例为过滤第一列添加了一个下拉列表,为过滤其他列添加了文本框。如果 DataTables 插件以服务器端模式初始化,过滤器也将通过 AJAX 调用发送到服务器端。您可以在 jQuery DataTables ColumnFilter 站点 上找到有关列过滤器配置的更多详细信息。
示例的最后一个必需部分是处理请求的控制器。
Controller
Controller 处理从浏览器发送的请求,并提供将在浏览器中显示的视图/数据。此处,Controller 有两个处理请求的方法:
- 当页面加载时返回视图页面的 Load 方法。
Employees
AJAX handler,当 jQuery DataTables 发送 AJAX 请求时返回员工。此操作将返回employees
数据,当 jQuery DataTables 插件想要刷新内容时,因此它应该接受定义表格当前视图状态的标准参数(当前页、每页项数等)。但是,为了支持刷新所选公司的表格(上面的案例 3),在此控制器操作中添加了 company ID 参数,该参数将用于根据公司进一步过滤员工。
第一个 Controller 方法非常简单。此方法仅返回将在浏览器中显示的视图,如以下列表所示:
public class HomeController : Controller
{
public ActionResult Index()
{
return View();
}
}
第二个 Controller 方法至关重要——它返回 employees
表格的 employees
。此方法显示在以下列表中:
public class HomeController : Controller
{
public ActionResult MasterDetailsAjaxHandler(
JQueryDataTableParamModel param, int? CompanyID)
{
var employees = DataRepository.GetEmployees();
//"Business logic" method that filters employees by the employer id
var companyEmployees = (from e in employees
where (CompanyID == null || e.CompanyID == CompanyID)
select e).ToList();
//UI processing logic that filter company employees by name and paginates them
var filteredEmployees = (from e in companyEmployees
where (param.sSearch == null ||
e.Name.ToLower().Contains(param.sSearch.ToLower()))
select e).ToList();
var result = from emp in filteredEmployees.Skip(
param.iDisplayStart).Take(param.iDisplayLength)
select new[] { Convert.ToString(emp.EmployeeID),
emp.Name, emp.Position };
return Json(new
{
sEcho = param.sEcho,
iTotalRecords = companyEmployees.Count,
iTotalDisplayRecords = filteredEmployees.Count,
aaData = result
},
JsonRequestBehavior.AllowGet);
}
}
方法的名称必须与 employees 数据表格中设置的 sAjaxSource
参数匹配。此方法接受一个封装 DataTables 插件发送的参数的对象(当前页、排序方向、要显示的项数等)。有关服务器端处理参数的更多详细信息,请参见本系列中的第一篇文章。除了此参数之外,还在方法签名中添加了一个名为 CompanyID
的附加参数。此参数仅与案例三相关,用于按选定的公司 ID 过滤员工。此参数的名称必须与案例 3 中 fnServerData
函数中添加的参数名称匹配。方法中的其他代码只是过滤 employee 数据并以 JSON 格式返回,这是 jQuery DataTables 插件所期望的。有关服务器端配置的更多详细信息,请参见本系列中的第一篇文章。
总结
本文展示了如何使用 jQuery DataTables 插件在 ASP.NET MVC 中轻松重新加载表格内容。客户端代码很少,服务器端只需标准的处理函数。此插件允许您以最少的精力和简单的实现指南创建有效的、AJAX 化的 Web 2.0 界面。您可以在此处下载以 ASP.NET MVC 实现的示例项目。
您可能还对本系列中其他文章感兴趣,这些文章展示了:
- 如何在 ASP.NET MVC 中使用 jQuery DataTables 插件实现服务器端处理。
- 如何使用 jQuery DataTables 和几个实现完整数据管理功能的 jQuery 插件在 ASP.NET MVC 中实现完全可编辑的表格。
我希望这些文章能在您实现 ASP.NET MVC 应用程序时有所帮助。
历史
- 2011 年 4 月 5 日:初始版本