Reputation: 4484
I am using datatables to dynamically render a table on my blade template. I have a series of checkboxes that user can check to show/hide table columns. All of this is working great.
This is what my template looks like:
template.blade.php
<table id="dataTables-report" class="table table-striped table-bordered table-hover">
</table>
Here is what I am using to render the table:
scripts.js
$('#dataTables-report').DataTable({
...
columnDefs: [
{
targets: 0,
title: 'Name',
searchable: true,
data: function (row, type, val, meta) {
// return row.data;
}
},
@if($report->order_date)
{
targets: 1,
title: 'Order Date',
searchable: false,
data: function (row, type, val, meta) {
// return row.data;
}
},
@endif
@if($report->order_number)
{
targets: 2, // could be 1 if order date is not selected
title: 'Order Number',
searchable: false,
data: function (row, type, val, meta) {
// return row.data;
}
},
@endif
...
});
"Order Date" is a checkbox that a user can choose to display on the table. If it is checked, it shows that column. Otherwise it does not.
It is possible that a different column could be selected first and it could be targets: 1
. Now if a user checks another box, targets
needs to dynamically get set to the next number. In this case: targets: 2
.
Each checkbox is stored as it's own column in the database, so I don't think I can do any sort of loop (hence a bunch of if statements). Otherwise, I think something like this would work.
Is there a way to dynamically generate the targets
number right in my blade template?
Upvotes: 1
Views: 1848
Reputation: 1
->addColumn('action', function ($floor) {
$action=
@Can("floor-edit"){"
<a class='btn btn-info btn-sm'
href=".route("floor.edit",Crypt::encrypt($floor->id))."><i class='fa fa-edit'></i>
</a>
<button type='button' name='delete' id=".Crypt::encrypt($floor->id)." class='delete btn btn-danger btn-sm'><i class='fa fa-trash'></i></button>
"};
return $action;
})
Upvotes: 0
Reputation: 15530
If you're seeking truly dynamic column visibility controlled by checkboxes (as I understood your ultimate goal), it can be done user-end entirely by few lines of jQuery.
In order to do that, you may simply
value
attribute to your <input>
nodes:change
event, find the column that is sourced (using column().dataSrc()
method) by the object property that corresponds to clicked checkbox value and adjust that column visibility (using .column().visible()
method accordingly:$('#checkboxWrapper').on('change', '[type="checkbox"]', event => {
let colindex = null;
dataTable.columns().every(function(){
if(this.dataSrc() == $(event.target).val()) colindex = this.index();
});
dataTable.column(colindex).visible($(event.target).prop('checked')).draw();
});
Complete live demo of that concept you may find below:
//sample source data
const dataSrc = [
{id: 1, item: 'apple', cat: 'fruit'},
{id: 2, item: 'carrot', cat: 'vegie'},
{id: 3, item: 'banana', cat: 'fruit'}
];
//extract all unique object keys from data source array
const checkboxes = [...new Set(dataSrc
.map(item => Object.keys(item))
.flat())];
//translate those into <input> nodes HTML
const checkboxesHtml = checkboxes.reduce((inputs, prop) => inputs += `<input type="checkbox" value="${prop}" checked>${prop}</input>`,'');
$('#checkboxWrapper').append(checkboxesHtml);
//initialize datatables
const dataTable = $('#example').DataTable({
data: dataSrc,
dom: 't',
columns: checkboxes.map(prop => ({title: prop, data: prop}))
});
//control columns visibility with checkboxes
$('#checkboxWrapper').on('change', '[type="checkbox"]', event => {
//grab column().index() that corresponds to checkbox value
let colindex = null;
dataTable.columns().every(function(){
if(this.dataSrc() == $(event.target).val()) colindex = this.index();
});
//toggle selected column visibility
dataTable.column(colindex).visible($(event.target).prop('checked')).draw();
});
<!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>
<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/1.10.19/css/jquery.dataTables.min.css">
</head>
<body>
<div id="checkboxWrapper"></div>
<table id="example"></table>
</body>
</html>
Upvotes: 1
Reputation: 4484
Thank you for your suggestions, here is what I came up with as a "quick" solution while I look further into your recommendations.
In my blade template, I created a global variable that I could access within my php.
@section('scripts')
<script>
$(function () {
...
let columnTarget = 0;
...
$('#dataTables-report').DataTable({
...
columnDefs: [
{
targets: columnTarget,
title: 'Name',
searchable: true,
data: function (row, type, val, meta) {
// return row.data;
}
},
@if($report->order_date)
{
targets: ++columnTarget,
title: 'Order Date',
searchable: false,
data: function (row, type, val, meta) {
// return row.data;
}
},
@endif
@if($report->order_number)
{
targets: ++columnTarget,
title: 'Order Number',
searchable: false,
data: function (row, type, val, meta) {
// return row.data;
}
},
@endif
...
</script>
@endsection
This seems to work well; correctly (dynamically) assigning the targets
value.
Upvotes: 0