Как повторно инициализировать dataTables с новыми данными с сервера с помощью ajax в 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
          });
}

Мой PartialViewResult в AdminController выглядит следующим образом:

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

Так что до сих пор это хорошо. Все идет хорошо, и в таблице отображаются только те новости, которые относятся к будущим дням. Теперь у меня есть возможность для администратора получать все новости из таблицы, включая прошедшие дни. Таким образом, я сохранил флажок в моем частичном представлении, как показано ниже, который является типом переключателя начальной загрузки:

<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 для этого конкретного флажка, как 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: таблица id = dailyNews - Невозможно повторно инициализировать DataTable. Для получения дополнительной информации об этой ошибке, пожалуйста, смотрите http://datatables.net/tn/3

Я посетил вышеупомянутую ссылку, но не смог ничего понять. Может кто-нибудь, пожалуйста, дайте мне знать, как вызвать метод контроллера json и вывести список новостей в эту таблицу?

Ответ 1

Сообщение об ошибке http://datatables.net/tn/3 точно определяет проблему. Вы повторно инициализируете таблицу с различными параметрами в fetchNews().

Сначала вам нужно уничтожить таблицу, см. 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, см. ниже.

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

Ответ 2

Это работало для меня после много исследований: - Сначала проверьте, существует ли dataTable или нет, если уничтожает dataTable, а затем воссоздает его

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

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

Ответ 3

У Datatables есть опция получения. Если ваша таблица получает другое содержимое после инициализации, вы можете установить параметр: 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
      });

}

Ответ 4

$ ( '# ТуЬаЫе') DataTable() уничтожить()..; $ ( '# ТуЬаЫе') HTML ( '');

Ответ 5

Хотя приведенные выше ответы относятся к симптому (предупреждение "Невозможно повторно инициализировать"), они не устраняют основную причину проблемы: вы не должны заполнять DataTable из jQuery $.load()/$.ajax()/$.get()/$.post() успешные обратные вызовы, потому что это вызывает всевозможные проблемы, вызванные асинхронной природой AJAX-вызовов.

.destroy() метод DataTables .destroy() вы можете сделать ситуацию еще хуже, поскольку каждый раз, когда вы извлекаете данные с сервера, вы без необходимости уничтожаете и заново создаете свой DataTable, который, по крайней мере, является пустой тратой производительности.

Вместо этого вам следует использовать опцию DataTables ajax которая запускает AJAX-вызов, где и когда это необходимо, позволяя вам в полной мере использовать методы API DataTables и не снижать производительность, например, для повторного извлечения данных вы просто делаете ajax.reload(), если вам необходимо изменить URL-адрес перед загрузкой актуальных данных, выполните ajax.url().load()

Полный живой DEMO примера 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="#" onclick="location.href='https://cdn.datatables.net/1.10.19/css/jquery.dataTables.min.css'; return false;">
</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>