Javascript 如何使用 MVC 中的 ajax 使用从服务器新获取的数据重新初始化数据表

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/29150480/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 02:55:29  来源:igfitidea点击:

How to reinitialize dataTables with newly fetched data from server using ajax in MVC

javascriptjqueryajaxasp.net-mvcdatatables

提问by Guruprasad Rao

So here I have list of menus for admin and under them I have Upload news. When this particular menu is clicked, I call a partial view as below.

所以这里我有管理员菜单列表,在它们下面我有上传新闻。单击此特定菜单时,我将调用局部视图,如下所示。

$("#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
          });
}

My PartialViewResult in AdminController is as below:

我在 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);
}

My _UploadNews.cshtml is as below

我的 _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="[email protected]">
                   <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="[email protected]"><span class="fa fa-edit"></span> </button>&nbsp; <button class="btn btn-danger" onclick="javascript: DeleteNews(this);" data-info="[email protected]"><span class="fa fa-trash-o"></span></button></td>
               </tr>
          }
     </tbody>
</table>

So till now it's good. Everything is going well and the table displays only those news which are of future days. Now I have a option for admin to fetch the whole set of news from table, including past days. So I have kept a checkbox in my partialview as below which is a bootstrap switch type:

所以到现在都还好。一切进展顺利,表格只显示未来几天的新闻。现在我可以选择让管理员从表中获取整套新闻,包括过去几天。所以我在我的部分视图中保留了一个复选框,如下所示,它是一个引导开关类型

<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">

and I have written a onswitchchangefor that particular checkbox as below:

onswitchchange为那个特定的复选框写了一个如下:

$("[name='fetchNews-checkbox']").on('switchChange.bootstrapSwitch', function (event, state) {
     if (state) 
     {
           fetchNews('all');
     }
     else 
     {
           fetchNews('upcoming');
     }
});

and my fetchNewsfunction is as below:

我的fetchNews功能如下:

function fetchNews(context)
{
    if(context!="")
    {
        $("#dailyNews").dataTable({
            "sPaginationType": "full_numbers",
            "bProcessing": true,
            "bServerSide": true,
            "sAjaxSource": "/Admin/FetchNews"
        });
    }
}

when this function is called I am getting an alert which says

当这个函数被调用时,我收到一个警报,上面写着

DataTables warning: table id=dailyNews - Cannot reinitialise DataTable. For more information about this error, please see http://datatables.net/tn/3

DataTables 警告:table id=dailyNews - 无法重新初始化 DataTable。有关此错误的更多信息,请参阅 http://datatables.net/tn/3

I visited the above said link but was not able to understand anything. Can anyone please let me know, how to call a controller json method and render list of news into this Table?

我访问了上述链接,但无法理解任何内容。谁能告诉我,如何调用控制器 json 方法并将新闻列表呈现到此表中?

回答by Gyrocode.com

The error message http://datatables.net/tn/3states the problem precisely. You're re-initializing the table with different options in fetchNews().

错误消息http://datatables.net/tn/3准确地说明了问题。您正在使用fetchNews().

You need to destroy the table first, see http://datatables.net/manual/tech-notes/3#destroy. You can do that with $("#dailyNews").dataTable().fnDestroy()(DataTables 1.9.x) or $("#dailyNews").DataTable().destroy()(DataTables 1.10.x).

您需要先销毁表,请参阅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 ...
        });
    }
}

Alternatively, if you're using DataTables 1.10.x, you can initialize the new table with additional option "destroy": true, see below.

或者,如果您使用的是 DataTables 1.10.x,您可以使用附加选项初始化新表"destroy": true,请参见下文。

function fetchNews(context)
{
     if(context!="")
     {
        $("#dailyNews").dataTable({
            "destroy": true,
            // ... skipped ...
        });
    }
}

回答by Ravi.Dudi

This worked for me after a lot of research:- First check if dataTable exist or not, if does destroy the dataTable and then recreate it

经过大量研究,这对我有用:-首先检查数据表是否存在,如果确实破坏了数据表,然后重新创建它

if ($.fn.DataTable.isDataTable("#mytable")) {
  $('#mytable').DataTable().clear().destroy();
}

$("#mytable").dataTable({...
                       
                });

回答by Dierp

Datatables has a retrieve option. If your table receive other content after inicialization you can set the parameter: retrieve: true,

数据表有一个检索选项。如果您的表在初始化后收到其他内容,您可以设置参数:retrieve: true,

You can watch the documentation here: https://datatables.net/reference/option/retrieve

您可以在此处观看文档: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
      });

}

}

回答by Joseph Ocampo

$('#mytable').DataTable().destroy(); $('#mytable').html('');

$('#mytable').DataTable().destroy(); $('#mytable').html('');

回答by Yevgen Gorbunkov

While above answers treat the symptom ('Cannot re-initialize'warning) they do not address the root cause of the problem: you shall notpopulate DataTable from within jQuery $.load()/$.ajax()/$.get()/$.post()success callbacks, because it raises all sorts of issues caused by async AJAX-call nature.

虽然上面的答案对待症状(“不能重新初始化”警告),他们没有解决问题的根源:你不得从jQuery的内部填充的DataTable $.load()/ $.ajax()/ $.get()/$.post()成功回调,因为它提出了造成异步的问题种种AJAX-调用性质。

By invoking DataTables .destroy()method you can make things even worse, as each time you retrieve the data from the server you unnecessarily destroy and create anew your DataTable which is a waste of performance at the very least.

通过调用 DataTables.destroy()方法,您可能会使事情变得更糟,因为每次从服务器检索数据时,您都会不必要地销毁并创建新的 DataTable,这至少会浪费性能。

Instead, you should make use of DataTables ajaxoption 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()

相反,您应该使用 DataTablesajax选项,它在需要的地方和时间触发 AJAX 调用,让您充分受益于 DataTables API 方法,而不是破坏性能,例如ajax.reload(),如果需要,只需重新获取您的数据即可在加载最新数据之前更改 URL,您可以ajax.url().load()

The complete live DEMOof OP's example might have looked as simple as that:

OP 示例的完整现场演示可能看起来很简单:

//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>