Reputation: 29683
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:
[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
@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> <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 onswitchchange
for that particular checkbox as below:
$("[name='fetchNews-checkbox']").on('switchChange.bootstrapSwitch', function (event, state) {
if (state)
{
fetchNews('all');
}
else
{
fetchNews('upcoming');
}
});
and my fetchNews
function is as below:
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
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?
Upvotes: 35
Views: 133427
Reputation: 380
I can reinitialize the data table everytime by providing the destroy property as show below:
.done(function(ret){
$("#cloud").DataTable({
ordering : true,
pageLength : 20,
destroy: true,
data : loadData(ret)
})
});
Upvotes: 2
Reputation: 321
Datatables has a retrieve option. If your table receive other content after inicialization you can set the parameter: retrieve: true
.
You can watch the documentation here.
$("#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
});
}
Upvotes: 4
Reputation: 1364
if ($.fn.DataTable.isDataTable("#mytable")) {
$('#mytable').DataTable().clear().destroy();
}
$("#mytable").DataTable({
...
});
Upvotes: 62
Reputation: 137
This will reload datatable with fresh content.
$("#dailyNews").dataTable().ajax.reload();
Upvotes: 0
Reputation: 669
This worked for me after a lot of research: $('#userList').DataTable().clear().destroy();
Upvotes: 0
Reputation: 15530
While above answers treat the symptom ('Cannot re-initialize' warning) they do not address the root cause of the problem: you shall not populate DataTable from within jQuery $.load()
/$.ajax()
/$.get()
/$.post()
success callbacks, because it raises all sorts of issues caused by async AJAX-call nature.
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.
Instead, you should make use of 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()
The complete live DEMO of OP's example might have looked as simple as that:
//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>
Upvotes: 3
Reputation: 58880
The error message http://datatables.net/tn/3 states the problem precisely. You're re-initializing the table with different options in 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).
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.
function fetchNews(context)
{
if(context!="")
{
$("#dailyNews").dataTable({
"destroy": true,
// ... skipped ...
});
}
}
Upvotes: 92