JQuery DataTables: Server-Side Search Function Breaking with SQL Error - laravel

I have a simple DataTable that I populate with data from a database, specifically from a single view called 'degree_inventory' as opposed to a traditional table. My application is written with Laravel, so I source my data using a route that pulls all the objects that correspond to a model and import them into my table. An additional level of complexity exists because the table has 'child rows', but those are not present by default.
My table:
<table id="program-table" class="table stripe compact">
<thead>
<tr>
<th>Levels</th>
<th>CIP Code</th>
<th>CIP Title</th>
<th>USF Title</th>
<th>Degree(s)</th>
<!-- <th>Activated Term</th>
<th>Suspended Term</th>
<th>Discontinued Term</th> -->
</tr>
</thead>
<tbody>
</tbody>
</table>
My DT declaration looks like:
$('#program-table').DataTable({
processing: true,
serverSide: true,
ajax: "{{ route('serverSide') }}",
columns: [
{
"className": 'details-control',
"orderable": false,
"data": null,
"width": '8%',
"defaultContent": ''
},
{ data: 'cip', width: '10%'},
{ data: 'cip_title' },
{ data: 'item_name' },
{ data: 'degree_name_list' }
],
pageLength: 25,
searching: true,
paging: true,
fixedHeader: true, //plugin not working
"order": [[ 1, "asc" ]] //by default order by cip code
});
And my 'serverSide' route that gets called looks like:
Route::get('/serverSide', [
'as' => 'serverSide',
'uses' => function () {
$model = \App\Degree::query();
return DataTables::eloquent($model)->make();
}
]);
The 'Degree' model is entirely empty except for defining the corresponding table to be 'degree_inventory'
The table initially populates, expands child rows, and paginates perfectly, but any query into the search bar returns the following error:
Column not found: 1054 unknown column 'degree_inventory' in 'where clause' followed by the raw query that attempts to find matches to entries in each row.
If anyone has any insight I'd be very appreciative. Thank you!

The issue was that I had a column of buttons to expand and collapse child rows.
The solution was to disable to searchable property of the expand/collapse column because the content of the column is exclusively images.
For example:
$('#example').dataTable( {
"columns": [
{ "searchable": false }, //first column is the expand button
null,
null,
null,
null
] } );
} );

Related

Unable to populate data in DataTable from Controller in Codeingiter

I am trying to list data with DataTable using server side processing through ajax. I am getting the expected response from the controller when the ajax hits. But the data is still not populated in the dataTable.
Controller
public function get_role_details() {
$this->load_generic_model(array('mst_role_model'));
$draw = intval($this->input->get("draw"));
$start = intval($this->input->get("start"));
$length = intval($this->input->get("length"));
$selected_rol = array('m_role_id','m_role_name');
$condition = array('m_role_status' => 'enable');
$other_configs = array('order_by' => 'm_role_id', 'order_dir' => 'DESC');
// $other_configs
$get_role = $this->mst_role_model->get_where_selected( $selected_rol, $condition, $other_configs);
if( (empty($get_role)) || !($get_role) )
{
echo json_encode(array('status' => 500, 'msg' => 'Server Error, Try again later'));
return false;
}
$data['role'] = $get_role;
$data['role_cnt'] = count($get_role);
$json_data = json_encode(array('status' => 200, 'data' => $data));
echo $json_data;
}
View
<section class="content">
<div class="box">
<div class="box-body">
<table id="logTable1" class="table" width="100%">
<thead>
<th>Role id</th>
<th>Role Name</th>
</thead>
</table>
</div>
</div>
</section>
<script type="text/javascript">
$(document).ready(function() {
$("#logTable1").DataTable({
'processing': false,
'serverSide': true,
'ajax': {
'url':'<?php echo base_url()."role/get_role_details"; ?>',
'type' : 'POST'
},
'columns' : [
{data : 'm_role_id'},
{data : 'm_role_name'}
]
});
});
</script>
I use something similar the following
$( document ).ready(function() { // when document is ready load
$.ajax({ // create an AJAX call...
type: $(this).attr('method'), // GET or POST
url: "<?php echo base_url("controller/function/"); ?>", // the file to call
success: function(response) { // on success..
var dts=JSON.parse(response) // becomes your array
var dataSet =dts.result;
// I specified the results in your case data to just call one filter then create the data table within the success call
$('#table_name').DataTable( {
data: dataSet,
fixedHeader: true,
dom: 'Bfrtip',
buttons: [
'copyHtml5',
'excelHtml5',
'csvHtml5',
'pdfHtml5',
],
columns: [
{ title: "Who",
data: "username",
defaultContent: ""
},
{
title: "Accepted",
data: "accepted_when",
render: function ( data, type, row ) {
var rowgpd = moment(data).format("Do MMM YYYY HH:mm:ss");
return rowgpd;
}},
{ title: "Status",
data: "status",
defaultContent: ""
},
]
} );
}
});
return false; // cancel original event to prevent form submitting
});
I believe it will do exactly as you want.
Its pretty straight forward I think .
So for me I had to parse the response to remove the json encoding and allow me to call the row and columns from the array. I also use moment js to parse the date and display in a better format.
Data array location DataTables requires an array of items to represent
the table's data, where each item in the array is a row. The item is
typically an object or an array (discussed in more detail below) - so
the first thing we need to do is tell DataTables where that array is
in the data source.
https://datatables.net/manual/ajax
Based on your screenshot, your JSON response appears to be this:
{
"data": {
"role": [{
"m_role_id": "47",
"m_role_name": "Aakash"
}, {
"m_role_id": "46",
"m_role_name": "Visiting Doctor"
}]
}
}
This is valid JSON, and it may be what you are expecting. But it is not what DataTables is expecting, when you are using DataTables with 'serverSide': true.
There are two problems:
You need to tell DataTables where the array (containing your row data) is located in your JSON - which in your case is data.role. Normally, you would do this using the dataSrc option:
'ajax': {
'url':'<?php echo base_url()."role/get_role_details"; ?>',
'type' : 'POST',
'dataSrc': 'data.role'
},
Because you are using server-side processing, your JSON response should use the structure shown in the server-side documentation:
{
"draw": 1,
"recordsTotal": 57,
"recordsFiltered": 57,
"data": [{
"m_role_id": "47",
"m_role_name": "Aakash"
}, {
"m_role_id": "46",
"m_role_name": "Visiting Doctor"
}]
}
Note the following:
The JSON needs to include those extra fields such as recordsTotal, to ensure pagination controls and information are displayed correctly.
The [ ... ] array is now directly attached to data in your JSON. There is no intermediate role object.
You can still keep role if you want to, but then you do still need to use dataSrc, as described above.
I recommend you follow the structure in the documentation, for simplicity.

How to sort Datatable by days in string value

I am currently using Datatable in my laravel project for displaying my day configuration from my database. I would like to display my data in the following order, Monday -> Tuesday -> Wednesday etc.
Currently it is being ordered by alphabetical order from my database where the day column is store as string. Below are my javascript codes for my table.
var ophrTables = $('#ophrs_table').DataTable({
stateSave: true,
columnDefs: [{
"searchable": false,
"orderable": false,
"targets": 0
},{
"searchable": true,
"orderable": true,
"targets": 1
},{
"searchable": false,
"orderable": false,
"targets": 2
},{
"searchable": false,
"orderable": false,
"targets": 3
}],
order: [[ 1, 'asc' ]]
});
Here are two approaches:
Use a Column Renderer
You can create a mapping from day names to numbers:
var days = { 'Monday': 1, 'Tuesday': 2, 'Wednesday': 3, 'Thursday': 4, 'Friday': 5, 'Saturday': 6, 'Sunday': 7 };
You can then use that mapping when you create your DataTable.
Here is my test data in my HTML table:
<table id="example" class="display dataTable cell-border" style="width:100%">
<thead>
<tr>
<th>Name</th>
<th>Day</th>
</tr>
</thead>
<tbody>
<tr>
<td>Tiger Nixon</td>
<td>Monday</td>
</tr>
<tr>
<td>Garrett Winters</td>
<td>Tuesday</td>
</tr>
<tr>
<td>Ashton Cox</td>
<td>Wednesday</td>
</tr>
<tr>
<td>Cedric Kelly</td>
<td>Thursday</td>
</tr>
<tr>
<td>Airi Satou</td>
<td>Friday</td>
</tr>
<tr>
<td>Brielle Williamson</td>
<td>Saturday</td>
</tr>
<tr>
<td>Herrod Chandler</td>
<td>Sunday</td>
</tr>
</tbody>
</table>
Here is my DataTable definition:
$('#example').DataTable( {
"columnDefs": [ {
"targets": 1,
"render": function ( data, type, row, meta ) {
if (type === 'sort') {
return days[data];
} else {
return data;
}
}
} ]
} );
For the second column (index = 1), I use a render function to map from the name of the day to an integer. DataTables will use this integer for sorting operations (type === 'sort'). Otherwise it will use the name of the day.
The days[data] expression is used to look up the relevant number from my days variable.
The data looks like this when it is sorted by day name:
Warning:
When you use a renderer which produces numeric sort data from data which is alphanumeric, you do have to be careful. Even though numbers are used for sorting, they are treated as alphanumeric. In our case, this makes no difference, because the string values "1" through "7" are sorted the same way as the integer values 1 through 7.
But if you wanted to do something similar with the months of the year, then you would run into problems, as October (10), November (11) and December (12) would potentially be mis-sorted.
One fix for this is to force the column to be treated as if it contains numeric data by default: "type": "num",. Credit to this answer for highlighting this potential issue.
(Forcing the return value to be an integer does not help: return parseInt(days[data]);).
Delegated Sorting
An alternative approach is to populate the relevant number into an extra column when you load your data into the table.
In your DataTable definition, you can hide this column:
"columnDefs": [
{ "visible": false, "targets": 2 }
]
Then you can use the DataTables orderData option to delegate sorting from the visible "day name" column to the hidden "day number" column:
"columnDefs": [
{ "visible": false, "targets": 2 },
{ "orderData": [ 1 ], "targets": 2 }
]
This tells DataTables to use the data in column index 2 when you sort on column index 1.
I don't think that you can order by day. May be you can put a hidden text in the datatable column.
Now
<td>Monday</td>
<td>Tuesday</td>
<td>Friday</td>
Change it to
<td><span style="display:none">1</span>Monday</td>
<td><span style="display:none">2</span>Tuesday</td>
<td><span style="display:none">5</span>Friday</td>
Once you change it to this style, you can order by day.

Datatable doesn't include multiple header rows into exported pdf file

Here is my HTML for datatable:
<table id="assessment-data-datatable-{{ $assessor->user_id }}">
<thead>
<tr class="success">
<th>Assessee: {{ $assignment->assessee->fullname }}</th>
<th>Assessor: {{ $assessor->fullname }}</th>
<th>Status: {{ $assessor->pivot->status }} </th>
</tr>
<tr>
<th>Parameter</th>
<th>Assessment</th>
<th>Provided on</th>
</tr>
</thead>
</table>
And here is the js code:
var dt = $('#assessment-data-datatable-' + assessorId).DataTable({
processing: true,
serverSide: true,
ajax: '/assessment/' + assessmentId + '/' + assessorId + '/fetch',
columns: [
{ data: 'parameter', defaultContent: 'N/A' },
{ data: 'assessment_value', defaultContent: 'N/A' },
{ data: 'created_at', defaultContent: 'N/A' }
],
dom: 'Bfrtip',
buttons: [
{
extend: 'pdf',
filename: assesseeName + ' assessment by ' + assessorName,
exportoptions: {
header: true,
footer: true
}
}
],
destroy: true
});
Above code works pretty well and it also exports the content into a pdf file. But into the exported pdf file, there is only second header row getting generated. Somehow the first row of the < header > gets excluded. I have also tried to move that row into < tfoot > and then export, but it also gets excluded there as well.
I think the issue here is that datatable only allows to export at max one row from the table header.
See here that how it exludes a row in header: (pdf screenshot)
Any help would be appreciated.
Thanks,
Parth Vora
I guess feature to export multiple rows into header is not yet implemented in datatable itself.
See datattable owner answer here:
https://github.com/DataTables/Buttons/pull/55
And I found that why it was not exporting table footer.
This code:
buttons: [
{
extend: 'pdf',
filename: assesseeName + ' assessment by ' + assessorName,
exportoptions: {
header: true,
footer: true
}
}
]
Should be like this:
buttons: [
{
extend: 'pdf',
filename: assesseeName + ' assessment by ' + assessorName,
},
header: true,
footer: true
]
header and footer option should be on the outer object.

Serverside processing with CoideIgniter and Ignited-Datatables

I read many tutorial, I googled but I still can not figure out the problem. Something must be wrong, or I just simply do not understand a part of it.
I have some database tables which has over 10k rows. I want to load only 1 page (50 rows), and I want the processing to happen on paging, searching or at filtering and to not to load all rows from the database.
What am I missing? Thanks!
I am using the lastest version of codeigniter and ignited datatables.
Controller (for table creation):
$tmpl = array('table_open' => '<table id="logs" class="table table-striped table-hover">');
$this->table->set_template($tmpl);
$data['title'] = 'Activity log';
$this->table->set_heading('Time', 'User', 'Activity');
$this->load->view('templates/header', $data);
$this->load->view('templates/sidebar');
$this->load->view('logs/activity');
$this->load->view('templates/footer');
Controller (for data):
$this->datatables->select('id, log_change_id as activity, timestamp, users_id')
->from('log');
echo $this->datatables->generate();
View's content:
$(document).ready(function () {
var oTable = $('#logs').dataTable({
"Processing": true,
"ServerSide": true,
"columns": [
{ "data": "timestamp" },
{ "data": "users_id" },
{ "data": "activity" }
],
"ajax": '<?php echo base_url(); ?>database/activity',
"language": {
'sLoadingRecords': '<div class="text-center"><i class="fa fa-5x fa-refresh fa-spin"></i></div>'
},
});
});
My whole life was a lie. Changed this, to that and its working like charm.
"Processing": true,
"ServerSide": true,
That:
processing: true,
serverSide: true,

Datatables Child Rows Implementation

Recently, I got a requirement for an implementation of adding Child rows in a table. I have gone through the few APIs and found that datatables fits into my requirement. As of now I am implementing this web application in Springs and getting the data from the controller.
That is $resultSet.
Now this dynamic data I have to render in jsp page. Here I got stucked because I am not able to implement with datatable. I have seen the example of http://datatables.net/examples/api/row_details.html and tried removing Ajax data and used c:foreach loop in place it. But i didn't get any luck.
So can you guys please tell me how do I use datatables with the dyncamic data in order to display child rows.
My main concern is:
$(document).ready(function() {
var table = $('#example').DataTable( {
"ajax": "../ajax/data/objects.txt",
"columns": [
{
"className": 'details-control',
"orderable": false,
"data": null,
"defaultContent": ''
},
{ "data": "name" },
{ "data": "position" },
{ "data": "office" },
{ "data": "salary" }
],
"order": [[1, 'asc']]
} );
How do I represent the above block.
I tried with <table id="xx"> <c:foreach loop to iterate>
You can use data option to feed data into DataTables directly instead of using server-side script to return data via Ajax. This initialization option can be useful when creating a table from a JavaScript data source, or from a custom Ajax data get. However the data has to be of type Array.
I'm not familiar with Spring framework but I'm assuming you can produce a string with data in JSON format and output it in your page to assign to table_data_json. I'm using a sample JSON string var table_data_json = '[ /* skipped */ ]';.
/* Formatting function for row details - modify as you need */
function format ( d ) {
// `d` is the original data object for the row
return '<table cellpadding="5" cellspacing="0" border="0" style="padding-left:50px;">'+
'<tr>'+
'<td>Full name:</td>'+
'<td>'+d.name+'</td>'+
'</tr>'+
'<tr>'+
'<td>Extension number:</td>'+
'<td>'+d.extn+'</td>'+
'</tr>'+
'<tr>'+
'<td>Extra info:</td>'+
'<td>And any further details here (images etc)...</td>'+
'</tr>'+
'</table>';
}
$(document).ready(function() {
var table_data_json = '[{"name":"Tiger Nixon","position":"System Architect","salary":"$320,800","start_date":"2011/04/25","office":"Edinburgh","extn":"5421"},{"name":"Garrett Winters","position":"Accountant","salary":"$170,750","start_date":"2011/07/25","office":"Tokyo","extn":"8422"},{"name":"Ashton Cox","position":"Junior Technical Author","salary":"$86,000","start_date":"2009/01/12","office":"San Francisco","extn":"1562"}]';
var table = $('#example').DataTable( {
"data": JSON.parse(table_data_json),
"columns": [
{
"className": 'details-control',
"orderable": false,
"data": null,
"defaultContent": ''
},
{ "data": "name" },
{ "data": "position" },
{ "data": "office" },
{ "data": "salary" }
],
"order": [[1, 'asc']]
} );
// 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');
}
} );
} );
td.details-control {
background: url('https://raw.githubusercontent.com/DataTables/DataTables/1.10.7/examples/resources/details_open.png') no-repeat center center;
cursor: pointer;
}
tr.shown td.details-control {
background: url('https://raw.githubusercontent.com/DataTables/DataTables/1.10.7/examples/resources/details_close.png') no-repeat center center;
}
<link href="//cdn.datatables.net/1.10.7/css/jquery.dataTables.min.css" rel="stylesheet" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script src="//cdn.datatables.net/1.10.7/js/jquery.dataTables.min.js"></script>
<table id="example" class="display">
<thead>
<tr>
<th></th>
<th>Name</th>
<th>Position</th>
<th>Office</th>
<th>Salary</th>
</tr>
</thead>
<tfoot>
<tr>
<th></th>
<th>Name</th>
<th>Position</th>
<th>Office</th>
<th>Salary</th>
</tr>
</tfoot>
</table>
If I misunderstood your question, please let me know and I will update my answer.

Resources