Guruprasad J Rao
Guruprasad J Rao

Reputation: 29683

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

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?

Upvotes: 35

Views: 133427

Answers (8)

rslj
rslj

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

Joseph Ocampo
Joseph Ocampo

Reputation: 61

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

Upvotes: 3

Dierp
Dierp

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

Ravi.Dudi
Ravi.Dudi

Reputation: 1364

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

Upvotes: 62

Arun Verma
Arun Verma

Reputation: 137

This will reload datatable with fresh content.

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

Upvotes: 0

Mahesh Narwade
Mahesh Narwade

Reputation: 669

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

Upvotes: 0

Yevhen Horbunkov
Yevhen Horbunkov

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

Gyrocode.com
Gyrocode.com

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

Related Questions