如何使用 MVC 中的 ajax 使用从服务器新获取的数据重新初始化数据表
How to reinitialize dataTables with newly fetched data from server using ajax in MVC
所以这里我有管理员菜单列表,在它们下面我有上传新闻。单击此特定菜单时,我调用如下所示的部分视图。
$("#body_data").load("/Admin/GetDailyNews", function () {
$("#dailyNews").dataTable({
"lengthMenu": [[5, 10, 25, 50, -1], [5, 10, 25, 50, "All"]],
"columnDefs": [{ "targets": 3, "orderable": false }],
"pagingType": "full_numbers",
"oLanguage": { "sSearch": "" },
"deferRender": true
});
}
我在 AdminController 中的 PartialViewResult 如下:
[HttpGet]
public PartialViewResult GetDailyNews()
{
var context=new MyContext();
List<AVmodel.NewsEventsViewModel> model = new List<AVmodel.NewsEventsViewModel>();
List<news> news = (from n in context.news where n.stdate >= System.DateTime.Now orderby n.stdate descending select n).ToList();
foreach (var NEWS in news)
{
model.Add(new AVmodel.NewsEventsViewModel()
{
EDate = NEWS.stdate,
EDesc = NEWS.brief,
EName = Convert.ToString(NEWS.name),
NID = NEWS.nid
});
}
return PartialView("_UploadNews", model);
}
我的_UploadNews.cshtml如下
@model IEnumerable<MCB.Models.BusinessObjects.AVmodel.NewsEventsViewModel>
<table id="dailyNews" cellspacing="0" width="100%" class="table table-condensed table-hover table-responsive table-bordered order-column">
<thead>
<tr>
<th>Event Date</th>
<th>Event Name</th>
<th>Detailed News</th>
<th class="disabled">Actions</th>
</tr>
</thead>
<tbody>
@foreach (var news in Model)
{
<tr data-row="row_@news.NID">
<td>@news.EDate.Date.ToShortDateString()</td>
<td>@Convert.ToString(news.EName)</td>
<td>@Convert.ToString(news.EDesc)</td>
<td><button class="btn btn-primary" data-target="#editAddNews" data-toggle="modal" onclick="javascript: EditNews(this);" data-info="data_@news.NID"><span class="fa fa-edit"></span> </button> <button class="btn btn-danger" onclick="javascript: DeleteNews(this);" data-info="data_@news.NID"><span class="fa fa-trash-o"></span></button></td>
</tr>
}
</tbody>
</table>
到目前为止,一切都很好。一切进展顺利,table 仅显示未来几天的新闻。现在,管理员可以选择从 table 获取整套新闻,包括过去几天。所以我在我的部分视图中保留了一个复选框,如下所示,它是 bootstrap 开关类型 :
<input type="checkbox" name="fetchNews-checkbox" data-on-text="All News" data-off-text="Upcoming News" data-on-color="primary" data-off-color="default" data-label-width="100px" data-label-text="News details">
我已经为那个特定的复选框写了一个 onswitchchange
,如下所示:
$("[name='fetchNews-checkbox']").on('switchChange.bootstrapSwitch', function (event, state) {
if (state)
{
fetchNews('all');
}
else
{
fetchNews('upcoming');
}
});
我的fetchNews
函数如下:
function fetchNews(context)
{
if(context!="")
{
$("#dailyNews").dataTable({
"sPaginationType": "full_numbers",
"bProcessing": true,
"bServerSide": true,
"sAjaxSource": "/Admin/FetchNews"
});
}
}
当这个函数被调用时,我收到一个警告
DataTables warning: table id=dailyNews - Cannot reinitialise
DataTable. For more information about this error, please see
http://datatables.net/tn/3
我访问了上面所说的link但是什么都看不懂。谁能告诉我,如何调用控制器 json 方法并将新闻列表呈现到此 Table?
错误消息 http://datatables.net/tn/3 准确地说明了问题。您正在使用 fetchNews()
中的不同选项重新初始化 table。
你需要先摧毁table,见http://datatables.net/manual/tech-notes/3#destroy。
您可以使用 $("#dailyNews").dataTable().fnDestroy()
(DataTables 1.9.x) 或 $("#dailyNews").DataTable().destroy()
(DataTables 1.10.x).
function fetchNews(context)
{
if(context!="")
{
// Destroy the table
// Use $("#dailyNews").DataTable().destroy() for DataTables 1.10.x
$("#dailyNews").dataTable().fnDestroy()
$("#dailyNews").dataTable({
// ... skipped ...
});
}
}
或者,如果您使用的是 DataTables 1。10.x,您可以使用附加选项 "destroy": true
初始化新的 table,见下文。
function fetchNews(context)
{
if(context!="")
{
$("#dailyNews").dataTable({
"destroy": true,
// ... skipped ...
});
}
}
经过大量研究,这对我有用:- 首先检查 dataTable 是否存在,
如果确实销毁数据表然后重新创建它
if ($.fn.DataTable.isDataTable("#mytable")) {
$('#mytable').DataTable().clear().destroy();
}
$("#mytable").dataTable({...
});
Datatables 有检索选项。如果您的 table 在初始化后收到其他内容,您可以设置参数: retrieve: true,
您可以在此处观看文档:https://datatables.net/reference/option/retrieve
$("#body_data").load("/Admin/GetDailyNews", function () {
$("#dailyNews").dataTable({
retrieve: true,
"lengthMenu": [[5, 10, 25, 50, -1], [5, 10, 25, 50, "All"]],
"columnDefs": [{ "targets": 3, "orderable": false }],
"pagingType": "full_numbers",
"oLanguage": { "sSearch": "" },
"deferRender": true
});
}
$('#mytable').DataTable().destroy();
$('#mytable').html('');
虽然以上答案治标不治本('Cannot re-initialize' 警告),但并未解决问题的根本原因:您不应 从 jQuery $.load()
/$.ajax()
/$.get()
/$.post()
成功回调中填充数据表,因为它引发了由异步引起的各种问题 AJAX-call自然.
通过调用 DataTables .destroy()
方法,您可能会使事情变得更糟,因为每次您从服务器检索数据时,您都会不必要地破坏并重新创建您的 DataTable,这至少会浪费性能。
相反,您应该使用 DataTables ajax
option which triggers AJAX-call where and when it is necessary allowing you to fully benefit from DataTables API methods and not screwing the performance, e.g to re-fetch your data you simply do ajax.reload()
, if you need to change URL before loading up to date data, you do ajax.url().load()
OP 示例的完整实时 DEMO 看起来可能就这么简单:
//initialize DataTables
const dataTable = $('#newsTable').DataTable({
//specify AJAX source, params and response source
ajax: {
url: 'https://newsapi.org/v2/everything',
data: () => ({
q: ($('input[name="subject"]:checked').val() || 'javascript'),
language: 'en',
apiKey: '699ba21673cd45aba406b1984b480b60'
}),
dataSrc: 'articles'
},
//set up table columns
columns: [
{title: 'Source', data: 'source.name'},
{title: 'Title', data: 'title'},
{title: 'Content', data: 'content'}
]
});
//trigger table data re-fetch with new subject
$('input[name="subject"]').on('change', () => dataTable.ajax.reload())
<!doctype html>
<html>
<head>
<script type="application/javascript" src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<script type="application/javascript" src="https://cdn.datatables.net/1.10.19/js/jquery.dataTables.min.js"></script>
<script type="application/javascript" src="test.js"></script>
<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/1.10.19/css/jquery.dataTables.min.css">
</head>
<body>
<label>Pick the subject:</label>
<input type="radio" name="subject" value="python">python</input>
<input type="radio" name="subject" value="javascript">javascript</input>
<table id="newsTable"></table>
</body>
</html>
经过大量研究,这对我有用:
$('#userList').DataTable().clear().destroy();
我每次都可以通过提供销毁 属性 来重新初始化数据 table,如下所示:
.done(function(ret){
$("#cloud").DataTable({
ordering : true,
pageLength : 20,
destroy: true,
data : loadData(ret)
})
});
这将重新加载包含新内容的数据表。
$("#dailyNews").dataTable().ajax.reload();
所以这里我有管理员菜单列表,在它们下面我有上传新闻。单击此特定菜单时,我调用如下所示的部分视图。
$("#body_data").load("/Admin/GetDailyNews", function () {
$("#dailyNews").dataTable({
"lengthMenu": [[5, 10, 25, 50, -1], [5, 10, 25, 50, "All"]],
"columnDefs": [{ "targets": 3, "orderable": false }],
"pagingType": "full_numbers",
"oLanguage": { "sSearch": "" },
"deferRender": true
});
}
我在 AdminController 中的 PartialViewResult 如下:
[HttpGet]
public PartialViewResult GetDailyNews()
{
var context=new MyContext();
List<AVmodel.NewsEventsViewModel> model = new List<AVmodel.NewsEventsViewModel>();
List<news> news = (from n in context.news where n.stdate >= System.DateTime.Now orderby n.stdate descending select n).ToList();
foreach (var NEWS in news)
{
model.Add(new AVmodel.NewsEventsViewModel()
{
EDate = NEWS.stdate,
EDesc = NEWS.brief,
EName = Convert.ToString(NEWS.name),
NID = NEWS.nid
});
}
return PartialView("_UploadNews", model);
}
我的_UploadNews.cshtml如下
@model IEnumerable<MCB.Models.BusinessObjects.AVmodel.NewsEventsViewModel>
<table id="dailyNews" cellspacing="0" width="100%" class="table table-condensed table-hover table-responsive table-bordered order-column">
<thead>
<tr>
<th>Event Date</th>
<th>Event Name</th>
<th>Detailed News</th>
<th class="disabled">Actions</th>
</tr>
</thead>
<tbody>
@foreach (var news in Model)
{
<tr data-row="row_@news.NID">
<td>@news.EDate.Date.ToShortDateString()</td>
<td>@Convert.ToString(news.EName)</td>
<td>@Convert.ToString(news.EDesc)</td>
<td><button class="btn btn-primary" data-target="#editAddNews" data-toggle="modal" onclick="javascript: EditNews(this);" data-info="data_@news.NID"><span class="fa fa-edit"></span> </button> <button class="btn btn-danger" onclick="javascript: DeleteNews(this);" data-info="data_@news.NID"><span class="fa fa-trash-o"></span></button></td>
</tr>
}
</tbody>
</table>
到目前为止,一切都很好。一切进展顺利,table 仅显示未来几天的新闻。现在,管理员可以选择从 table 获取整套新闻,包括过去几天。所以我在我的部分视图中保留了一个复选框,如下所示,它是 bootstrap 开关类型 :
<input type="checkbox" name="fetchNews-checkbox" data-on-text="All News" data-off-text="Upcoming News" data-on-color="primary" data-off-color="default" data-label-width="100px" data-label-text="News details">
我已经为那个特定的复选框写了一个 onswitchchange
,如下所示:
$("[name='fetchNews-checkbox']").on('switchChange.bootstrapSwitch', function (event, state) {
if (state)
{
fetchNews('all');
}
else
{
fetchNews('upcoming');
}
});
我的fetchNews
函数如下:
function fetchNews(context)
{
if(context!="")
{
$("#dailyNews").dataTable({
"sPaginationType": "full_numbers",
"bProcessing": true,
"bServerSide": true,
"sAjaxSource": "/Admin/FetchNews"
});
}
}
当这个函数被调用时,我收到一个警告
DataTables warning: table id=dailyNews - Cannot reinitialise DataTable. For more information about this error, please see http://datatables.net/tn/3
我访问了上面所说的link但是什么都看不懂。谁能告诉我,如何调用控制器 json 方法并将新闻列表呈现到此 Table?
错误消息 http://datatables.net/tn/3 准确地说明了问题。您正在使用 fetchNews()
中的不同选项重新初始化 table。
你需要先摧毁table,见http://datatables.net/manual/tech-notes/3#destroy。
您可以使用 $("#dailyNews").dataTable().fnDestroy()
(DataTables 1.9.x) 或 $("#dailyNews").DataTable().destroy()
(DataTables 1.10.x).
function fetchNews(context)
{
if(context!="")
{
// Destroy the table
// Use $("#dailyNews").DataTable().destroy() for DataTables 1.10.x
$("#dailyNews").dataTable().fnDestroy()
$("#dailyNews").dataTable({
// ... skipped ...
});
}
}
或者,如果您使用的是 DataTables 1。10.x,您可以使用附加选项 "destroy": true
初始化新的 table,见下文。
function fetchNews(context)
{
if(context!="")
{
$("#dailyNews").dataTable({
"destroy": true,
// ... skipped ...
});
}
}
经过大量研究,这对我有用:- 首先检查 dataTable 是否存在, 如果确实销毁数据表然后重新创建它
if ($.fn.DataTable.isDataTable("#mytable")) {
$('#mytable').DataTable().clear().destroy();
}
$("#mytable").dataTable({...
});
Datatables 有检索选项。如果您的 table 在初始化后收到其他内容,您可以设置参数: retrieve: true,
您可以在此处观看文档:https://datatables.net/reference/option/retrieve
$("#body_data").load("/Admin/GetDailyNews", function () {
$("#dailyNews").dataTable({
retrieve: true,
"lengthMenu": [[5, 10, 25, 50, -1], [5, 10, 25, 50, "All"]],
"columnDefs": [{ "targets": 3, "orderable": false }],
"pagingType": "full_numbers",
"oLanguage": { "sSearch": "" },
"deferRender": true
});
}
$('#mytable').DataTable().destroy(); $('#mytable').html('');
虽然以上答案治标不治本('Cannot re-initialize' 警告),但并未解决问题的根本原因:您不应 从 jQuery $.load()
/$.ajax()
/$.get()
/$.post()
成功回调中填充数据表,因为它引发了由异步引起的各种问题 AJAX-call自然.
通过调用 DataTables .destroy()
方法,您可能会使事情变得更糟,因为每次您从服务器检索数据时,您都会不必要地破坏并重新创建您的 DataTable,这至少会浪费性能。
相反,您应该使用 DataTables ajax
option which triggers AJAX-call where and when it is necessary allowing you to fully benefit from DataTables API methods and not screwing the performance, e.g to re-fetch your data you simply do ajax.reload()
, if you need to change URL before loading up to date data, you do ajax.url().load()
OP 示例的完整实时 DEMO 看起来可能就这么简单:
//initialize DataTables
const dataTable = $('#newsTable').DataTable({
//specify AJAX source, params and response source
ajax: {
url: 'https://newsapi.org/v2/everything',
data: () => ({
q: ($('input[name="subject"]:checked').val() || 'javascript'),
language: 'en',
apiKey: '699ba21673cd45aba406b1984b480b60'
}),
dataSrc: 'articles'
},
//set up table columns
columns: [
{title: 'Source', data: 'source.name'},
{title: 'Title', data: 'title'},
{title: 'Content', data: 'content'}
]
});
//trigger table data re-fetch with new subject
$('input[name="subject"]').on('change', () => dataTable.ajax.reload())
<!doctype html>
<html>
<head>
<script type="application/javascript" src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<script type="application/javascript" src="https://cdn.datatables.net/1.10.19/js/jquery.dataTables.min.js"></script>
<script type="application/javascript" src="test.js"></script>
<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/1.10.19/css/jquery.dataTables.min.css">
</head>
<body>
<label>Pick the subject:</label>
<input type="radio" name="subject" value="python">python</input>
<input type="radio" name="subject" value="javascript">javascript</input>
<table id="newsTable"></table>
</body>
</html>
经过大量研究,这对我有用: $('#userList').DataTable().clear().destroy();
我每次都可以通过提供销毁 属性 来重新初始化数据 table,如下所示:
.done(function(ret){
$("#cloud").DataTable({
ordering : true,
pageLength : 20,
destroy: true,
data : loadData(ret)
})
});
这将重新加载包含新内容的数据表。
$("#dailyNews").dataTable().ajax.reload();