35

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>&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 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?

8 Answers 8

92

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 ...
        });
    }
}
Sign up to request clarification or add additional context in comments.

Comments

62
  • 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({
    ...
});

2 Comments

it's not working for me my datatable version is 1.9.4 I am not able to re intialized it in Angular JS
I'm lacking .clear() in my code for it to works! Thanks!
4

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

1 Comment

Is this something new option added with datatable? If yes please attach the source along with datatables version too.. :) It will be helpful for others.
3

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>

Comments

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

1 Comment

Please consider adding an explanation for your code.
2

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

Comments

0

This worked for me after a lot of research: $('#userList').DataTable().clear().destroy();

Comments

0

This will reload datatable with fresh content.

$("#dailyNews").dataTable().ajax.reload();

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.