I have a mysql table with about 30000 rows. I have to put all rows in a DataTable and load each segment each time a table page is loaded (when you click on pagination). I saw that I can use the deferLoading parameter in my JS, but when I use it my pages are not loading. As you can see, I have to load images, so I absolutely have to do a light loading of the content...
Here is my HTML :
<table class="table table-striped table-bordered table-hover datatable products-datatable">
<thead>
<tr>
<th></th>
<th><?=_("Product")?></th>
<th></th>
</tr>
</thead>
<tfoot>
<tr>
<th></th>
<th><?=_("Product")?></th>
<th></th>
</tr>
</tfoot>
</table>
Here is my JS :
var table = $('.products-datatable').dataTable( {
"order": [[ 1, "asc" ]],
"processing": true,
"serverSide": true,
"deferLoading": 30000,
"ajax": {
url: location.protocol + '//' + location.hostname + '/ajax/products.php?action=list',
type: "POST"
},
"columns": [
{ "data": "image",
"orderable": false,
"width": "80px" },
{ "data": "product" },
{ "data": "action",
"orderable": false,
"width": "20px",
"sClass": "class",
}
]
});
Here is my AJAX :
$req = $pdo->prepare('SELECT product_id, name FROM products');
if ( $req->execute() ) {
if ($req->rowCount()) {
$result['draw'] = 1;
$result['recordsTotal'] = $req->rowCount();
$result['recordsFiltered'] = 10;
$result['data'] = array();
$result['DT_RowId'][] = array();
while( $row = $req->fetch() ) {
if ($row['name']) { $name = $row['name']; } else { $name = "N/A"; }
$result['data'][] = array( "DT_RowId" => $row['product_id'],
"DT_RowClass" => 'myclass',
"image" => '<img src="' . HOSTNAME.'assets/img/products/' . $row['product_id'] . '.jpg" class="product_thumb">',
"product" => '' . $name . '',
"action" => "<i class=\"fa fa-close fa-2x text-danger\"></i>"
);
}
}
}
$req->closeCursor();
I'm sure there is something I missed... :-(
I believe you don't need to use deferLoading to benefit from server-side processing.
Your current script just returns all records and doesn't do sorting or filtering. You need to use ssp.class.php (available in DataTables distribution package) or emran/ssp class to correctly handle AJAX requests on the server.
DataTables library will send start and length parameters in AJAX request indicating which portion of the data is needed and your server-side processing class will correctly handle it for you.
Please see an example of server-side processing for more information.
Related
I want to populate a jQuery datatable based on the content of a textarea. Note: my datatables implementation is not serverside. That is: sorting/filtering happens on the client.
I know my php works as it returns expected results in my test scenario (see below). I have included a lot of code to provide context. I am new to datatables and php.
My html looks like this:
// DataTable Initialization
// (no ajax yet)
$('#selectedEmails').DataTable({
select: {
sytle: 'multiple',
items: 'row'
},
paging: false,
scrollY: '60vh',
scrollCollapse: true,
columns: [
{data: "CONICAL_NAME"},
{data: "EMAIL_ADDRESS"}
]
});
// javascript that defines the ajax (called by textarea 'onfocus' event)
function getEmails(componentID) {
deselectTabs();
assignedEmails = document.getElementById(componentID).value.toUpperCase().split(",");
alert(JSON.stringify(assignedEmails)); //returns expected json
document.getElementById('email').style.display = "block";
//emailTable = $('#selectedEmails').DataTable();
try {
$('#selectedEmails').DataTable().ajax =
{
url: "php/email.php",
contentType: "application/json",
type: "POST",
data: JSON.stringify(assignedEmails)
};
$('#selectedEmails').DataTable().ajax.reload();
} catch (err) {
alert(err.message); //I get CANNOT SET PROPERTY 'DATA' OF null
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<!-- table skeleton -->
<table id="selectedEmails" class="display" style="width: 100%">
<thead>
<tr>
<th colspan='2'>SELECTED ADDRESSES</th>
</tr>
<tr>
<th>Conical Name</th>
<th>Email Address</th>
</tr>
</thead>
</table>
<!-- textarea definition -->
<textarea id='distribution' name='distribution' rows='3'
style='width: 100%' onblur="validateEmail('INFO_DISTRIBUTION', 'distribution');"
onfocus="getEmails('distribution');">
</textarea>
The following code returns the expected json:
var url = "php/email.php";
emailList = ["someone#mycompany.com","someoneelse#mycompany.com"];
fetch(url, {
method: 'post',
body: JSON.stringify(emailList),
headers: {
'Content-Type': 'application/json'
}
}).then(function (response) {
return response.text();
}).then(function (text) {
alert( JSON.stringify( JSON.parse(text))); //expencted json
}).catch(function (error) {
alert(error);
});
php code:
require "openDB.php";
if (!$ora) {
$rowsx = array();
$rowx = array("CONICAL_NAME" => "COULD NOT CONNECT", "EMAIL_ADDRESS" => "");
$rowsx[0] = $rowx;
echo json_encode($rowsx);
} else {
//basic query
$query = "SELECT CONICAL_NAME, EMAIL_ADDRESS "
. "FROM SCRPT_APP.BCBSM_PEOPLE "
. "WHERE KEY_EMAIL LIKE '%#MYCOMANY.COM' ";
//alter query to get specified entries if first entry is not 'everybody'
if ($emailList[0]!='everybody') {
$p = 0;
$parameters = array();
foreach ($emailList as $email) {
$parmName = ":email" . $p;
$parmValue = strtoupper(trim($email));
$parameters[$p] = array($parmName,$parmValue);
$p++;
}
$p0=0;
$query = $query . "AND KEY_EMAIL IN (";
foreach ($parameters as $parameter) {
if ($p0 >0) {
$query = $query.",";
}
$query = $query.$parameter[0];
$p0++;
}
$query = $query . ") ";
$query = $query . "ORDER BY CONICAL_NAME";
$getEmails = oci_parse($ora, $query);
foreach ($parameters as $parameter) {
oci_bind_by_name($getEmails, $parameter[0], $parameter[1]);
}
}
oci_execute($getEmails);
$row_num = 0;
try {
while (( $row = oci_fetch_array($getEmails, OCI_ASSOC + OCI_RETURN_NULLS)) != false) {
$rows[$row_num] = $row;
$row_num++;
}
$jsonEmails = json_encode($rows, JSON_INVALID_UTF8_IGNORE);
if (json_last_error() != 0) {
echo json_last_error();
}
} catch (Exception $ex) {
echo $ex;
}
echo $jsonEmails;
oci_free_statement($getEmails);
oci_close($ora);
}
Looking at a couple of examples on the DataTables site, I found I was making this more difficult than it needed to be: Here is my solution:
HTML: (unchanged)
<table id="selectedEmails" class="display" style="width: 100%">
<thead>
<tr>
<th colspan='2'>SELECTED ADDRESSES</th>
</tr>
<tr>
<th>Conical Name</th>
<th>Email Address</th>
</tr>
</thead>
</table>
<textarea id='distribution' name='distribution' rows='3'
style='width: 100%'
onblur="validateEmail('INFO_DISTRIBUTION', 'distribution');"
onfocus="getEmailsForTextBox('distribution');">
</textarea>
javascript:
Note: The key was the function for data: which returns json. (My php code expects json as input, and of course, outputs json).
[initialization]
var textbox = 'developer'; //global variable of id of textbox so datatables can use different textboxes to populate table
$(document).ready(function () {
$('#selectedEmails').DataTable({
select: {
sytle: 'multiple',
items: 'row'
},
ajax: {
url: "php/emailForList.php",
contentType: "application/json",
type: "post",
data: function (d) {
return JSON.stringify(document.getElementById(textbox).value.toUpperCase().split(","));
},
dataSrc: ""
},
paging: false,
scrollY: '60vh',
scrollCollapse: true,
columns: [
{data: "CONICAL_NAME"},
{data: "EMAIL_ADDRESS"}
]
});
});
[code that redraws table]
function getEmailsForTextBox(componentID) {
deselectTabs();
document.getElementById('email').style.display = "block";
textbox = componentID; //textbox is global variable that DataTable uses as source control
$('#selectedEmails').DataTable().ajax.reload();
}
I have generated a data table using the Datatables jquery plugin. The table is populated with JSON.
I want to extract cell values when I make a selection to use in a URL but I can't get it to work.
#I'm using django
import json
#my list
users = [[1,26,'John','Smith'],[2,33,'Dave','Johnson'],[1,22,'Aaron','Jones']]
#my json
user_json = json.dumps(users)
<table class="table table-striped- table-bordered table-hover table-checkable" id="user-table">
<thead>
<tr>
<th>Age</th>
<th>Record ID</th>
<th>First Name</th>
<th>Last Name</th>
<th>Actions</th>
</tr>
</thead>
</table>
<script type="text/javascript">
var userData = {{user_json|safe}};
</script>
var SourceHtml = function() {
var dataJSONArray = userData;
var initTable1 = function() {
var table = $('#user-table');
// begin table
table.DataTable({
responsive: true,
data: dataJSONArray,
columnDefs: [
{
targets: -1,
title: 'Actions',
orderable: false,
render: function(data, type, full, meta) {
//this is where I need help. I need for each a-tag to link to a django url pattern such as href="{% url 'users:select-user' id=id_value %}"
return '<i class="la la-edit"></i>';
},
},
],
});
};
return {
//main function to initiate the module
init: function() {
initTable1();
}
};
}();
jQuery(document).ready(function() {
SourceHtml.init();
});
I need a href link to a django url pattern such as href="{% url 'users:select-user' id=id_value %}" in each a tag. however, I can't get the values from the cells.
Datatables columns.render option can be used to access full data source of current row.
By using columns.render as function type, we can use third (3)
parameter to access another column index form same row of data
source.
var userData = [[1,26,'John','Smith'],[2,33,'Dave','Johnson'],[1,22,'Aaron','Jones']];
$('#example').dataTable( {
"columnDefs": [ {
"targets": -1,
"data": null,
"title": 'Actions',
"render": function ( data, type, row, meta ) {
return 'Download';
}
} ]
} );
I search in all web,i.e Google, datatable docs, datatable .. and not found the solution.
I use Symfony 4 and follow this text, https://datatables.net/examples/server_side/simple.html and https://datatables.net/manual/server-side. Then my code is that:
<html>
<table id="datatable" class="table table-striped table-bordered dataTable no-footer" role="grid" aria-describedby="datatable_info">
<thead>
<tr class="headings">
<th></th>
<th class="column-title">Número/Ano</th>
<th class="column-title">Cadastrado em</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
<script>
var table = $('#datatable').DataTable( {
"serverSide": true,
"info": true,
"stateSave": true,
"ajax":{
"url":"/decreto/filter",
"type": "GET"
},
"language": {
"url": "//cdn.datatables.net/plug-ins/1.10.16/i18n/Portuguese-Brasil.json"
},
"lengthMenu": [ 5, 10, 15, 25 ],
"columns": [
{
"className": 'details-control',
"orderable": false,
"data": null,
"defaultContent": ''
},
{
"data": "number",
"render": function ( data, type, row ) {
var z = "";
data = data.toString();
for (;(4-data.length)>z.length;z = z.concat("0"));
return z+data+"/"+row.year;
},
},
{
"data":"registry.date",
"render": function ( data ) {
var dMy = data.split(" ")[0].split("-");
var time = data.split(" ")[1].split(".")[0];
return dMy[2]+"/"+dMy[1]+"/"+dMy[0]+" "+time;
},
},
],
//*/
"order": [[1, 'asc']]
} );
</script>
My Controller return that:
$source = $request->query->get("search")["value"];
$rows = $request->query->get("length");
....
return new JsonResponse(
array(
'draw'=>intval(1),
'recordsTotal'=>intval($em->total()["total"]),
'recordsFiltered'=>intval(count($list)),
'data'=>$list,
)
);
When the page load at first time, this work fine, return only 5 rows like I define. But if I try to filter, don't work.
For debug what was send, I change the method in Symfony, switch GET for Post, and return an error with the URL:
jquery.min.js:4 GET http://localhost:8000/decreto/filter?draw=1&columns%5B0%5D%5Bdata%5D=&columns%5B0%5D%5Bname%5D=&columns%5B0%5D%5Bsearchable%5D=true&columns%5B0%5D%5Borderable%5D=false&columns%5B0%5D%5Bsearch%5D%5Bvalue%5D=&columns%5B0%5D%5Bsearch%5D%5Bregex%5D=false&columns%5B1%5D%5Bdata%5D=number&columns%5B1%5D%5Bname%5D=&columns%5B1%5D%5Bsearchable%5D=true&columns%5B1%5D%5Borderable%5D=true&columns%5B1%5D%5Bsearch%5D%5Bvalue%5D=&columns%5B1%5D%5Bsearch%5D%5Bregex%5D=false&columns%5B2%5D%5Bdata%5D=registry.date&columns%5B2%5D%5Bname%5D=&columns%5B2%5D%5Bsearchable%5D=true&columns%5B2%5D%5Borderable%5D=true&columns%5B2%5D%5Bsearch%5D%5Bvalue%5D=&columns%5B2%5D%5Bsearch%5D%5Bregex%5D=false&columns%5B3%5D%5Bdata%5D=files&columns%5B3%5D%5Bname%5D=&columns%5B3%5D%5Bsearchable%5D=true&columns%5B3%5D%5Borderable%5D=true&columns%5B3%5D%5Bsearch%5D%5Bvalue%5D=&columns%5B3%5D%5Bsearch%5D%5Bregex%5D=false&columns%5B4%5D%5Bdata%5D=4&columns%5B4%5D%5Bname%5D=&columns%5B4%5D%5Bsearchable%5D=true&columns%5B4%5D%5Borderable%5D=true&columns%5B4%5D%5Bsearch%5D%5Bvalue%5D=&columns%5B4%5D%5Bsearch%5D%5Bregex%5D=false&order%5B0%5D%5Bcolumn%5D=1&order%5B0%5D%5Bdir%5D=asc&start=0&length=5&search%5Bvalue%5D=el&search%5Bregex%5D=false&_=1520304436769 405 (Method Not Allowed)
Then I fix the method to filter the request sent, was send :
DecretoController.php on line 194:
array:7 [▼
"draw" => "1"
"columns" => array:5 [▶]
"order" => array:1 [▼
0 => array:2 [▶]
]
"start" => "0"
"length" => "5"
"search" => array:2 [▼
"value" => "el"
"regex" => "false"
]
"_" => "1520302968156"
]
The content is like says https://datatables.net/manual/server-side.
Oh right then, and continuous with the says the site above, my controller returned:
DecretoController.php on line 224:
array:4 [▼
"draw" => 1
"recordsTotal" => 6
"recordsFiltered" => 1
"data" => array:1 [▼
0 => array:13 [▶]
]
]
Data has 1 element, the match with i lookup. Until then, fine! The fine, finish here. Make the jsonResponse the change for:
{"draw":1,"recordsTotal":6,"recordsFiltered":1,"data":
[{"id":"XYgrQvzrYrYY","number":2,"year":2018,"publish":{"date":"2018-01-11 00:00:00.000000","timezone_type":3,"timezone":"UTC"},"created":{"date":"2018-01-02 00:00:00.000000","timezone_type":3,"timezone":"UTC"},"description":"asfasfasdfasdfsadfsadfsd (admitido pelo sdfasdf), o sr. sfasdfasfas.","registry":{"date":"2018-03-02 02:04:22.000000","timezone_type":3,"timezone":"UTC"},"active":1,"user_id":1,"user_first_name":"Eu,"unidade_id":7,"unidade_name":"Co do Munic\u00edpio","files":[]}]}
What's wrong?
- Load at first page OK
- Search is working
- Return like order on documentation
I use https://code.jquery.com/jquery-1.12.4.js
Thanks ..
:(
because you have fixed draw value, which should be sequence for every request.
explaination:
first load. datatables request draw=1. php return draw=1 . this works fine.
if you do any action (sort, search, filter etc). datatables will request draw=2. php return draw=1. error happened. because request draw is not match with response draw
try change 'draw'=>intval(1), to 'draw'=>intval($_GET['draw']),
There is a good example on how to use JQuery Datatables with Core MVC at Using jQuery DataTables Grid With ASP.NET CORE MVC
I download the sample project, made some modifications and it works perfectly.
However, I'm getting an error when I try to integrate this into my project.
DataTables warning: table id=example - Requested unknown parameter 'IdStudent' for row 0, column 0. For more information about this error, please see http://datatables.net/tn/4
After I click ok on the error, the table generates with the correct number of rows, but with no data:
This is my class:
public class GridStudent
{
[Key]
public int IdStudent { get; set; }
public string Name { get; set; }
public string LastName { get; set; }
}
The HTML and JavaScript:
<div class="container">
<br />
<div style="width:90%; margin:0 auto;">
<table id="example" class="table table-striped table-bordered dt-responsive nowrap" width="100%" cellspacing="0">
<thead>
<tr>
<th>IdStudent</th>
<th>Name</th>
<th>LastName</th>
<th>Edit</th>
<th>Delete</th>
</tr>
</thead>
</table>
</div>
</div>
<script>
$(document).ready(function ()
{
$("#example").DataTable({
"processing": true, // for show progress bar
"serverSide": true, // for process server side
"filter": true, // this is for disable filter (search box)
"orderMulti": false, // for disable multiple column at once
"ajax": {
"url": "/StudentGrid/LoadData",
"type": "POST",
"datatype": "json"
},
"columnDefs":
[
{
"targets": [0],
"visible": false,
"searchable": false,
}
],
"columns": [
{ "data": "IdStudent", "name": "IdStudent", "autoWidth": true },
{ "data": "Name", "name": "Name", "autoWidth": true },
{ "data": "LastName", "name": "LastName", "autoWidth": true },
{
"render": function (data, type, full, meta)
{ return '<a class="btn btn-info" href="/StudentGrid/Edit/' + full.IdStudent + '">Edit</a>'; }
}
,
{
data: null, render: function (data, type, row)
{
return "<a href='#' class='btn btn-danger' onclick=DeleteData('" + row.IdStudent + "'); >Delete</a>";
}
},
]
});
});
function DeleteData(CustomerID)
{
if (confirm("Are you sure you want to delete ...?"))
{
Delete(CustomerID);
}
else
{
return false;
}
}
function Delete(CustomerID)
{
var url = '#Url.Content("~/")' + "StudentGrid/Delete";
$.post(url, { ID: CustomerID }, function (data)
{
if (data)
{
oTable = $('#example').DataTable();
oTable.draw();
}
else
{
alert("Something Went Wrong!");
}
});
}
</script>
This is the line of code, from the controller, than returns the data:
return await Task.Run(() => Json(new { draw = draw, recordsFiltered = recordsTotal, recordsTotal = recordsTotal, data = data }));
As you can see from the image, the controller is returning the data correctly, but for some reason DataTables can't read it.
I cross check with the sample a thousand times and I can't see a difference on the format of the data being return.
Any suggestions?
This is most likely due to the casing of the serialized JSON. Your data properties in the column definitions within your JavaScript expect Pascal casing. At present, I expect your are serializing JSON as lower camel case rather than Pascal case (e.g. idStudent instead of IdStudent).
To serialize JSON as Pascal case, make sure you have the following in the ConfigureServices method in your Startup class:
services
.AddMvc()
.AddJsonOptions(options =>
{
options.SerializerSettings.ContractResolver
= new Newtonsoft.Json.Serialization.DefaultContractResolver();
});
I have an issues with datatable show entries 、sorting and filter basically all the JS function not working. I've already include the JS files. some details:my DataTables is server-side processing and retrieve data in json from serverside .
datatable.php
<script type="text/javascript" charset="utf8" src="//code.jquery.com/jquery-1.12.3.js"></script>
<script type="text/javascript" charset="utf8" src="https://cdn.datatables.net/1.10.12/js/jquery.dataTables.min.js"></script>
<script>
$(document).ready(function() {
$.fn.dataTable.ext.errMode = 'none';
var table = $('#example').DataTable( {
"processing": true,
"serverSide": true,
"jQueryUI": true,
"ordering": true,
"searching": true,
"order": [[1, 'desc']],//set column 1 (time)
"ajax": {
url: "process.php",
type: 'POST',
data: {
from: "<?php echo $from; ?>",
to: "<?php echo $to; ?>"
}
},
"columns": [
{
"className":'details-control',
"orderable":false,
"data":null,
"defaultContent": ''
},
{ "data": "time"},
{ "data": "message",
"render": function ( data, type, row )
{
data = data.replace(/&/g, "&").replace(/>/g, ">").replace(/</g, "<").replace(/"/g, """);
return type === 'display' && data.length > 200 ?
'<span title="'+data+'">'+data.substr( 0, 98 )+'...</span>' :data;
}
}
]
} );
// Add event listener for opening and closing details
$('#example tbody').on('click', 'td.details-control', function () {
var tr = $(this).closest('tr');
var row = table.row( tr );
if ( row.child.isShown() ) {
// This row is already open - close it
row.child.hide();
tr.removeClass('shown');
}
else {
// Open this row
row.child( format( row.data())).show();
tr.addClass('shown');
}
} );
} );
</script>
<body>
<table id="example" class="display" cellspacing="0" width="100%">
<thead>
<tr>
<th ></th>
<th data-search-index="3">time</th>
<th data-search-index="3">Message</th>
</tr>
</thead>
<tfoot>
<tr>
<th></th>
<th>time</th>
<th>Message</th>
</tr>
</tfoot>
</table>
</body>
process.php
$search='';
$requestData= $_REQUEST;
if(isset($_POST["search"]["value"]) && !empty($_POST["search"]["value"])){
$search ='&q=_all:'.$_POST["search"]["value"];
}
$qryurl ='<ip>/log/_search?size=10'.$search ;
if ( !empty($requestData['start']) && $requestData['length'] != '-1' )
{
$qryurl ='<ip>/log/_search?size=10&from='.$requestData['start'].$search;
}
.......
//json output
$results = array(
"draw" => intval($requestData['draw']),
"iTotalRecords" =>intval($total),
"iTotalDisplayRecords" => intval($total),
"aaData"=>$sourceary
);
now I can see the table but I just can't sorting or searching and show more entries. any suggestion? Thank a lot, More
I think you need add a objects to your DataTable:
ordering: true,
searching: true,
order: [[0, 'asc']]//default
To your PHP code than you must add something like this for ordering:
if(count($_POST['order'])){
$orderBy = $_POST['columns'][$_POST['order'][0]['column']]['data'];
$orderDir = $_POST['order'][0]['dir'];
}
And for searching:
if(isset($_POST["search"]["value"]) && !empty($_POST["search"]["value"])){
$search = $_POST["search"]["value"];
}
For entries you must put this variables to your url:
$howMany = (isset($_POST['length'])) ? intval($_POST['length']) : 10;//10 is default its size param
$start = (isset($_POST['start'])) ? intval($_POST['start']) : 0;
And put this variables to your query.