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

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.

Related

Individual column filtering using datatable

My target is to have an individual filtering for column. My reference is: https://datatables.net/extensions/fixedheader/examples/options/columnFiltering.html
The problem I am encountering right now when I type, my datatable doesn't do any filtering and it shows an error regarding CURSORPOSITION:
I followed the guide thoroughly and made a lots of research but I still failed to achieve my goal. I hope you can help me
Views:
<table id="example" class="table table-bordered table-hover table-striped is-narrow is-hoverable is-fullwidth text-nowrap" style="width: 100%;">
<thead>
<tr>
<th>TESTING ID</th>
<th>TESTING ACTION</th>
<th>TESTING DESC</th>
<th>TESTING Date</th>
<th>TESTING VENUE</th>
<th>TESTING TICKET</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
Ajax:
$(document).ready(function() {
$('#example thead tr')
.clone(true)
.addClass('filters')
.appendTo('#example thead');
table = $('#example').DataTable({
dom: 'lfrtip',
"processing": false, //Feature control the processing indicator.
"serverSide": true, //Feature control DataTables' server-side processing mode.
orderCellsTop: true,
fixedHeader: true,
initComplete: function () {
var api = this.api();
// For each column
api
.columns()
.eq(0)
.each(function (colIdx) {
// Set the header cell to contain the input element
var cell = $('.filters th').eq(
$(api.column(colIdx).header()).index()
);
var title = $(cell).text();
$(cell).html('<input type="text" placeholder="' + title + '" />');
// On every keypress in this input
$(
'input',
$('.filters th').eq($(api.column(colIdx).header()).index())
)
.off('keyup change')
.on('change', function (e) {
// Get the search value
$(this).attr('title', $(this).val());
var regexr = '({search})'; //$(this).parents('th').find('select').val();
var cursorPosition = this.selectionStart;
// Search the column for that value
api
.column(colIdx)
.search(
this.value != ''
? regexr.replace('{search}', '(((' + this.value + ')))')
: '',
this.value != '',
this.value == ''
)
.draw();
})
.on('keyup', function (e) {
e.stopPropagation();
$(this).trigger('change');
$(this)
.focus()[0]
.setSelectionRange(cursorPosition, cursorPosition);
});
});
},
// Load data for the table's content from an Ajax source
"ajax": {
"url": "<?php echo site_url('controller/lists')?>",
"type": "POST",
async:true,
dataType: "json",
"data": function(data){
},
},
//Set column definition initialization properties.
"columnDefs": [
{
"targets": [ 0 ], //first column
"orderable": false, //set not orderable
},
{
"targets": [ -1 ], //last column
"orderable": false, //set not orderable
},
],
});
});

Button click not working in Vue in datatable ajax render

I am a newbie in Vuejs.
I have a users table which is showing data using Server-side processing in Datatable. I am trying to add a click event which will call a vue function. But the click function is not working at all. I tried use these methods. But none of them are working.
v-on:click="functionName"
v-on:click="$emit('functionName')"
#click="functionName"
HTML part
<table class="table table-bordered data-table dataTable-load">
<thead class="thead-light">
<tr>
<th style="width: 80px;">No</th>
<th>Name</th>
<th>Email</th>
<th>Phone</th>
<th>Type</th>
<th>Created</th>
<th>Last Updated</th>
<th width="280px">Action</th>
</tr>
</thead>
<tbody></tbody>
</table>
<div>
<span v-html='data'></span>
</div>
SCRIPT part
var dt = $('.dataTable-load').DataTable({
processing: true,
serverSide: true,
ajax: {
url: "{{ url('user/getdata') }}",
type: "post",
data: {"_token": "{{ csrf_token() }}"}
},
columns: [
{name: 'id', data: 'id', },
{name: 'name', data: 'name'},
{name: 'email', data: 'email'},
{name: 'phone', data: 'phone'},
{name: 'usertype', data: 'usertype',
"render": function (data, type, row) {
if (row.usertype == 'M') {
return 'Manager';
} else {
return 'Staff';
}
}
},
{name: 'created_at', data: 'created_at'},
{name: 'updated_at', data: 'updated_at'},
{
title: 'msg',
"render": function (data, type, row) {
return '<button v-on:click="showModal" #click="showModal">the button</button>';
}
}
]
});
dt.on('order.dt search.dt', function () {
dt.column(0, {search: 'applied', order: 'applied'}).nodes().each(function (cell, i) {
cell.innerHTML = i + 1;
});
}).draw();
App.js
const app = new Vue({
el: '#app',
data: {
data: '',
},
methods: {
showModal() {
this.data = 'Now click on me <a href=\'#\' #click.prevent=\'alert("yo")\'> here </a>';
},
},
});
Please let me know how to do it correctly. Thanking you in advance.

Laravel Yajra DataTable - Fetch content via Ajax with supplied search parameters

After searching as to how to fill up a Yajra DataTable with data from an ajax call with user supplied search parameters, I came to this page for the official documentation.
It has a code snippet as follows...
$builder->ajax([
'url' => route('users.index'),
'type' => 'GET',
'data' => 'function(d) { d.key = "value"; }',
])
However, I cannot make anything out of it. Where does the $builder variable come from? How do I use the data received from the Ajax call to fill up the table? This page lists the callback functions with no details.
What I need
A full-blown example of how to fill up my data table with data received from an Ajax call initiated by the search button #btn_search after selecting a value from the drop-down #param.
For simplicity, lets assume that the table structure looks like...
<select id="param">
<option value="">Select </option>
<option value="1">One</option>
<option value="2">Two</option>
</select>
<button id="btn_search" value="Search">Search</button>
<table>
<thead>
<tr>
<th>Serial</th>
<th>Col1</th>
<th>Col2</th>
<th>Col3</th>
</tr>
</thead>
</table>
The controller method that returns the data...
<?php
public function getBasicData()
{
$users = User::select(['id','name','email','address']);
return Datatables::of($users)->make();
}
The user selects a value from the dropdown and clicks on the search button. In the actual scenario, several dropdowns are there to collect the search parameters. Relevant jQuery code is...
$("#btn_search").click(function() {
var param_value = $("#param").val().trim();
// make ajax call probably
});
How can I make the Ajax call inside the click handler and fill up the data table with the received data?
The $builder variable is the class id of the table that would view the information ,
Here is an example :
<table id="data" class="table table-bordered table-hover" >
<thead>
<tr class="table-head">
<th>#</th>
<th>namr</th>
<th>email</th>
<th>date</th>
<th>auth</th>
<th>control</th>
<th>control</th>
</tr>
</thead>
<tbody>
</tbody>
<tfoot>
<th> </th>
<th> </th>
<th> </th>
<th> </th>
<th></th>
<th></th>
<th></th>
</tfoot>
</table>
and this is ajax code
<script type="text/javascript">
var lastIdx = null;
var table = $('#data').DataTable({
processing: true,
serverSide: true,
ajax: '{{ url('/adminpanel/users/data') }}',
columns: [
{data: 'id', name: 'id'},
{data: 'name', name: 'name'},
{data: 'email', name: 'email'},
{data: 'created_at', name: 'created_at'},
{data: 'admin', name: 'isadmin'},
{data: 'edit', name: 'edit', orderable: false, searchable: false},
{data: 'action', name: 'action', orderable: false, searchable: false}
],
"language": {
"url": "{{ Request::root() }} /admin/cus/Arabic.json"
},
"stateSave": false,
"responsive": true,
"order": [[0, 'asc']],
"pagingType": "full_numbers",
aLengthMenu: [
[25, 50, 100, 200, -1],
[25, 50, 100, 200, "All"]
],
iDisplayLength: 25,
fixedHeader: true,
"oTableTools": {
"aButtons": [{
"sExtends": "csv",
"sButtonText": "ملف إكسل",
"sCharSet": "utf16le"
},
{
"sExtends": "copy",
"sButtonText": "نسخ المعلومات",
},
{
"sExtends": "print",
"sButtonText": "طباعة",
"mColumns": "visible",
}
],
"sSwfPath": "{{ Request::root() }} /website/admin/cus/copy_csv_xls_pdf.swf"
},
"dom": '<"pull-left text-left" T><"pullright" i><"clearfix"><"pull-right text-right col-lg-6" f > <"pull-left text-left" l><"clearfix">rt<"pull-right text-right col-lg-6" pi > <"pull-left text-left" l><"clearfix"> '
,initComplete: function ()
{
var r = $('#data tfoot tr');
r.find('th').each(function(){
$(this).css('padding', 8);
});
$('#data thead').append(r);
$('#search_0').css('text-align', 'center');
}
});
table.columns().eq(0).each(function(colIdx) {
$('input', table.column(colIdx).header()).on('keyup change', function() {
table
.column(colIdx)
.search(this.value)
.draw();
});
});
table.columns().eq(0).each(function(colIdx) {
$('select', table.column(colIdx).header()).on('change', function() {
table
.column(colIdx)
.search(this.value)
.draw();
});
$('select', table.column(colIdx).header()).on('click', function(e) {
e.stopPropagation();
});
});
$('#data tbody')
.on( 'mouseover', 'td', function () {
var colIdx = table.cell(this).index().column;
if ( colIdx !== lastIdx ) {
$( table.cells().nodes() ).removeClass( 'highlight' );
$( table.column( colIdx ).nodes() ).addClass( 'highlight' );
}
} )
.on( 'mouseleave', function () {
$( table.cells().nodes() ).removeClass( 'highlight' );
} );
</script>
this is a full table with ajax example ,like Yajara documentation help .

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

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

Bind Vue click function on dynamically created content from jquery

First of all I am new to vuejs., currently working on a project made using Laravel. I am using Vue where ever I feel the need for it. On a certain page I am using datatable to load list of machine requests
$list = LicenceRequests::orderBy('allocated')->with('users.userDetails')->where('users_id', '!=', 1)->get();
return Datatables::of($list)
->addColumn('actions', function ($list) {
return '<button data-id="'.$list->id.'" class="btn btn-success" #click="allocateEvent">Allocate</button>';
})
->addIndexColumn()
->rawColumns(['actions'])
->make(true);
I have added a click function so that When the datatable is rendered, a Vue function can be called. In the blade template, I am using the following html code :
<div id="content" class="content">
<div class="block">
<div class="block-content">
<table class="table table-bordered table-striped " id="requestList">
<thead>
<tr>
<th>Sr. No</th>
<th class="hidden-xs" >Name</th>
<th class="hidden-xs" >Email</th>
<th class="hidden-xs" >Requests</th>
<th class="hidden-xs" >Allocated</th>
<th class="hidden-xs" >Date requested</th>
<th class="hidden-xs" >Machine address</th>
<th class="text-center">Actions</th>
</tr>
</thead>
</table>
</div>
</div>
</div>?
For the datatable, I am calling it on the page load function as follows :
$(function (){
$('#requestList').dataTable({
processing: false,
serverSide: true,
ajax: '{!! route('admin.getLicenceRequests') !!}',
columns: [
{data: 'DT_Row_Index', orderable: false, searchable: false},
{ data: 'users.user_details.name', name: 'name' },
{ data: 'users.email', name: 'email' },
{ data: 'number', name: 'number' },
{ data: 'allocated', name: 'allocated' },
{ data: 'request_generated_on', name: 'request_generated_on' },
{ data: 'machine_address', name: 'machine_address' },
{ data: 'actions', name: 'actions',orderable: false, searchable: false }
],
lengthMenu: [[ 10, 15, 20], [ 10, 15, 20]]
});
});
I am initializing Vue on the same page
var vm = new Vue({
el: '#content',
methods: {
allocateEvent: function() {
console.log("hello");
}
}
})
The problem is that the function is not called when I press the button on the rendered html of datatable. If I bind the function to any otehr element fn the page it will work. Is there something I am missing or some Vue related code that I am not adding?
P.S I know this is not how Vue should be used with laravel blade. I just wanted to know why the above code is not working when it should.
Thanks
I don't think you can create a binding with dynamically rendered content like this. The problem is the vue application is created first and the content with the #click binding is rendered afterwards.
Here is a comment by Evan Yu regarding dynamic content:
https://forum-archive.vuejs.org/topic/151/vue-js-not-listening-to-dynamically-created-elements
It's suggested to use $compile(html) and appendChild when working with dynamic content.

Resources