Reputation: 2410
In my Laravel app, I have multiple pages where I have DataTables. They all have the class "mydttable". I load data into the DataTables using Ajax.
On each row of each table I have a column with a delete button. Whenever I press is, I execute a delete on the respective row, then I want to reload the data into the datatable
. I can do that by questioning which tabel had the button on it using if statements, but I am wondering if there is a simpler method to do this reload.
More exactly...
is my custom.js, I do the dataTable populating like bellow:
var uzTable = $('#users').DataTable( {
"processing": true,
"serverSide": true,
"sAjaxSource": "sspXController?draw=1",
...
});
var cliTable = $('#clients').DataTable( {
"processing": true,
"serverSide": true,
"sAjaxSource": "sspXController2?draw=1",
...
});
var marTable = $('#market').DataTable( {
"processing": true,
"serverSide": true,
"sAjaxSource": "sspXController3?draw=1",
...
});
and now, the on delete click event, where I do the delete and want to do the reloading
$( document ).on('click', '.ssDelete', function(e){
e.preventDefault();
$.ajax({
url: someFormAction,
type: 'POST',
dataType: 'html',
success:function(data) {
$(".mydttable").ajax.reload();
}
});
and my HTML is something like:
<table id="users" class="row-border hover order-column table mydttable dataTable no-footer" cellspacing="0" width="100%">
<thead>
<tr role="row">
<th class="small-sorting" style="width:84px"></th>
<th class="small-sorting" style="width:84px">Operatiuni</th>
</tr>
</thead>
<tbody>
<tr>
<td></td>
<td></td>
</tr>
</tbody>
</table>
Of course, the above HTML is just the one for the first DataTable ("users"), there is HTML code for the other tables also, but I wont paste it here to avoid making this question excessively long. Also at any given time, there is ONLY ONE dataTable displayed in View (html)
So when I click on any button with the ssDelete ID, I delete the current record of the currently shown dataTable, and I want to refresh the dataTable that contains the delete buttons. And since I did not do a delete function for each table separately, I would like to be able to also do things shorter for ajax reloading.
So, my goal is to be able to reload any DataTable that is loaded in the document when the "#ssDelete" button is clicked, without the need of additional asignments and conditionals... And my attempt is not working:
success:function(data) {
$(".mydttable").ajax.reload(); // NOT WORKING
...
How can I do this? EDIT People seem to not read my entire question, so I will repeat here the essence of it: I need to be able to have ONLY ONE function for deleting records from multiple dataTables. In order to do that (the delete part is DONE and WORKING already) I need to be able to refresh/reload the contents of the VISIBLE dataTable. And I need to do that without having to test what table is visible. Based on the fact that all my dataTables share the same class, I should be able to invoke a generic dataTable and apply to it the ajax.reload() function. But it does not work. I need a way to access whatever dataTable is in the current VIEW, using some generic way... something like:
$(".mydttable").ajax.reload();
or
$('.mydttable').dataTable().fnReloadAjax();
or
$('.mydttable').DataTable().ajax.reload();
Apparently if I do this, jQuery is trying to execute a function on a regular Table element, and not on a dataTable conversion of the Table. If I try to apply DataTable() to the element like above, I will get :
Uncaught TypeError: Cannot read property 'reload' of undefined
Here is my ajax call so far (also not working):
var idtable = $('.mydttable').attr('id');
$.ajax({
url: myFormAction,
type: 'POST',
cache: false,
data : { _token: csrf_token, _method:'DELETE' },
dataType: 'html',
success:function(data) {
$('#DeleteModalDialog').modal('hide');
if(idtable=='users'){
alert('uzerii');
uzTable.ajax.reload();
}else if(idtable=='clients'){
alert('Clients');
cliTable.ajax.reload();
}else if(idtable=='market'){
alert('Market');
marTable.ajax.reload();
}
}
});
So the reloading does not happen, even if I get the Alert, so it knows what is the visible table's ID. (The uzTable,cliTable and marTable are jquery vars as seen above)
What is wrong with my code...?How can I solve this?
Upvotes: 3
Views: 5793
Reputation: 3256
You'll want to use server side processing. Here is an example of how I do it.
$('.dtable').DataTable({
/*
* Shows message dialog of loading data for slow connections
*/
processing: true,
/*
* Does an ajax call to get the data
* Happens every time you search or sort
*/
serverSide: true,
/*
* full_numbers = first, last, next, previous, and numbers
* in the pagation
*/
pagingType: "full_numbers",
/*l = show X entries
* f = search box
* <> = div
* <"class" = class name
* t = table
* r = 'proccessing' dialog
* i = 10 out of 1000 records
* p = pagation
* */
dom: 'lf<"nstuff"p><"toolbar">trip',
/*
* Defines the ajax call
*/
ajax: {
url: 'url.php',
datatype: "json",
type: "post",
/*Adds data to ajax call*/
data: function(d) {
d.action = 'list';
}
},
/*Defines columns*/
columns: [
/* Everything in here is sent to server upon ajax call.
* Orderable false = no arrows to order by
* searchable false = doesn't search that column
* */
{
title: "name",
render: function() {
/*
* arguments[2] is the third parameter passed in through the
* function. it holds the entire row data in it.
*/
var row = arguments[2];
return "<a href='?" + row.id + "'>" + row.name + "</a>";
}
}, {
title: "Info",
"orderable": false,
render: function() {
return arguments[2].email;
}
}, {
title: "Action",
data: 'id',
"orderable": false
}
],
/*Orders from this to that*/
order: [
[0, 'asc']
]
});
<?php
function list($REQUEST) {
/*
* Draw is returned back to datatables in order for javascript to not render
* Older draws first in case of async ajax calls.
*/
$draw = $this->aspam($REQUEST, true, 'draw');
/* Query Handles the search field in the datatables plugin */
$query = $this->aspam($this->aspam($REQUEST, false, 'search'), false, 'value');
/* Data holds the extra variables */
$data = $this->aspam($REQUEST, false, 'data');
/* This is the array of order from datatables */
$order = $this->aspam($REQUEST, false, 'order');
/* Where to start the limit */
$start = $this->aspam($REQUEST, true, 'start');
/* how long the limit is */
$length = $this->aspam($REQUEST, true, 'length');
/* Set up all the variables defaults to not throw errors */
$orderby = '';
$where = '';
$first = TRUE;
/* if order is array itterate through it and set the order */
if (is_array($order)) {
foreach ($order as $o) {
if ($first) {
$first = FALSE;
} else {
$orderby .= ',';
}
/* 0 = Name
* $o[dir] is either asc or desc based on datatables
*/
switch ($o['column']) {
case 0:
case '0':
$orderby .= "entity_name $o[dir]";
break;
}
}
/* if not empty create the order by */
if (!empty($orderby)) {
$orderby = "ORDER BY $orderby";
}
}
/* if the search string is not empty search all the searchable fields */
if (!empty($query)) {
$where .= "
AND (
name like '%$query%'
)";
}
/* This is the selection query
* It creates the sql with out and with the where
*/
$sql_nowhere = ($sql = "
select from where
");
$sql_somewhere = ($sql .= "
$where
");
$sql .= "
$orderby
LIMIT $start,$length
";
/*
* after all the where and join clauses are created get the filtered
* count of all the records
*/
$recordsFiltered = $this->getCounts($sql_somewhere);
/* The total amount of records in this call */
$recordsTotal = $this->getCounts($sql_nowhere);
if (!$temp = $this->retrieve($sql)) {
/* if no results are shown create $temp as an empty array to not through errors */
$temp = [];
}
/* creates the datatables array that it likes so it won't through an error */
$array = array(
'draw' => $draw
, 'recordsTotal' => $recordsTotal
, 'recordsFiltered' => $recordsFiltered
, 'data' => $temp
);
return $array;
}
/**
* gets the total count of sql
* @param type $sql
* @return type
*/
function getCounts($sql) {
return $this->retrieve("SELECT count(*) as count FROM ($sql) as z")[0]['count'];
}
Other than that, I suggest using the click event on the button to trigger the delete.
$('button').click(function() {
var id = $(this).data('id');
deleteMe(id).done(function() {
$('dtable').reload();
});
});
function deleteMe(id) {
/*code for what ever you do with the id.*/
return $.ajax();
}
<button data-id="555">
Me
</button>
This script won't help you off the cuff, But it will point you in the right direction.
EDIT
var tables = [];
var options = [{
ajax: 1
}, {
ajax: 2
}, {
ajax: 3
}, {
ajax: 4
}, ];
$('dtable').each(function(index) {
$(this).data('id', index);
tables.push($(this).DataTables(options[index]));
});
$(document).on('click', '.ssDelete', function(e) {
var index = $(this).closest('dtable').data('id');
e.preventDefault();
$.ajax({
url: someFormAction,
type: 'POST',
dataType: 'html',
success: function(data) {
tables[index].ajax.reload();
}
});
});
<table class='dtable'></table>
<table class='dtable'></table>
<table class='dtable'></table>
<table class='dtable'></table>
every time you do a datatables it returns the datatable handle. You need to use that handle in order to refresh the table. I put up a way to add multiple tables at once without a lot of redundant code. Just make sure that your options.length
and dtable.length
is the same. Otherwise you'll through and index out of bounds.
Upvotes: 2