Referring to the Individual column searching (text inputs) and Individual column searching (select inputs) to use multiple filters on jQuery DataTable, I mixed them up in order to allow text inputs searches on some columns and select inputs searching on others.
It almost works, but select inputs don't work correctly: the first select input on the third column shows values of the first column, the second select input shows the second column, and so on.
$( document ).ready(function() {
$('#wbe_table tfoot th.search_th').each( function () {
var title = $(this).text();
$(this).html( '<input type="text" placeholder="Search '+title+'" />' );
} );
var oTable = $('#wbe_table').DataTable( {
orderCellsTop: true,
fixedHeader: true,
responsive: true,
lengthChange: true,
autoWidth: true,
pageLength: 50,
order: [[7, "desc"]],
columnDefs: [
{
targets: [4],
orderable: false
},
{
type: "currency",
targets: [7,8,9,10]
},
],
dom: 'Bfrtip',
buttons: [
'copy', 'csv', 'excel', 'pdf', 'print'
] ,
//Select input search
initComplete: function () {
var api = this.api();
$('.filterhead', api.table().footer()).each( function (i) {
var column = api.column(i);
var select = $('<select><option value=""></option></select>')
.appendTo( $(this).empty() )
.on( 'change', function () {
var val = $.fn.dataTable.util.escapeRegex(
$(this).val()
);
column
.search( val ? '^'+val+'$' : '', true, false )
.draw();
} );
column.data().unique().sort().each( function ( d, j ) {
select.append( '<option value="'+d+'">'+d+'</option>' );
} );
} );
}
});
// Text input search
oTable.columns().every( function () {
var that = this;
$( 'input', this.footer() ).on( 'keyup change', function () {
if ( that.search() !== this.value ) {
that
.search( this.value )
.draw();
}
} );
} );
});
I am having some trouble integrating some custom functionalities with Datatable and Datatable Editor at the same time.
Without server-side processing my current functionalities works perfectly but I want to be able to implement server-side filtering with Editor.
With server-side filtering these work:
1.Pagination
2.Global Search
3.Sorting
4.Row reorder
5.Dynamic Page length
With server-side filtering these don't work:
1.Custom column input filtering
2.Custom footer select filtering
My serverside script for Datatable and Editor:
Editor::inst($db, 'article_categories')
->fields(
Field::inst('article_categories.id')->validator('Validate::numeric'),
Field::inst('article_categories.name')->validator('Validate::notEmpty'),
Field::inst('article_categories.description'),
Field::inst('article_categories.rowOrder')->validator('Validate::numeric')
)
->on('preCreate', function ($editor, $values) {
if (!$values['article_categories']['rowOrder']) {
$next = $editor->db()->sql('select IFNULL(MAX(rowOrder)+1, 1) as next FROM article_categories')->fetch();
$editor->field('article_categories.rowOrder')->setValue($next['next']);
} else {
$editor->db()
->query('update', 'article_categories')
->set('rowOrder', 'rowOrder+1', false)
->where('rowOrder', $values['article_categories']['rowOrder'], '>=')
->exec();
}
})
->on('preRemove', function ($editor, $id, $values) {
$order = $editor->db()
->select('article_categories', 'rowOrder', array('id' => $id))
->fetch();
$editor->db()
->query('update', 'article_categories')
->set('rowOrder', 'rowOrder-1', false)
->where('rowOrder', $order['rowOrder'], '>')
->exec();
})
->process($request->all())
->json();
My client-side script:
Default config:
jQuery(function () {
$.extend(true, $.fn.dataTable.defaults, {
serverSide: true,
fixedHeader: true,
searchDelay: 800,
paging: true,
processing: true,
pageLength: 10,
info: true,
dom: "Blfrtip",
select: true,
responsive: true,
lengthMenu: [
[10, 25, 50, -1],
[10, 25, 50, "All"],
],
});
});
Datatable and Editor setup:
var editor;
jQuery(function () {
//Editor
editor = new $.fn.dataTable.Editor({
table: "#article-category",
ajax: {
url: "article-categories",
type: "POST",
},
fields: [
{
label: "Order:",
name: "article_categories.rowOrder",
type: "hidden",
fieldInfo:
"This field can only be edited via click and drag row reordering.",
},
{
label: "FAQ Category Name:",
name: "article_categories.name",
},
{
label: "Description (optional):",
name: "article_categories.description",
type: "textarea",
},
],
});
//Datatable
var table = $("#article-category").DataTable({
ajax: {
url: "article-categories",
type: "POST",
},
rowReorder: {
dataSrc: "article_categories.rowOrder",
editor: editor,
},
buttons: cms.editorFormButtons(editor),
initComplete: function () {
cms.headerInputFilter("article-category", this.api(), [1, 2]);
cms.footerSelectFilter(this.api(), [1, 2]);
},
columns: [
{
data: "article_categories.rowOrder",
name: "article_categories.rowOrder",
className: "reorder no-inline",
},
{
data: "article_categories.name",
name: "article_categories.name",
},
{
data: "article_categories.description",
name: "article_categories.description",
},
],
});
//Inline Editor
cms.inlineEdit("article-category", editor);
editor
.on("postCreate postRemove", function () {
table.ajax.reload(null, false);
})
.on("initCreate", function () {
editor.field("article_categories.rowOrder").enable();
})
.on("initEdit", function () {
editor.field("article_categories.rowOrder").disable();
});
});
Custom functions:
let footerSelectFilter = function (table, columns) {
if (typeof columns != "undefined" && typeof table != "undefined") {
table.columns(columns).every(function () {
var column = this;
var select = $('<select><option value=""></option></select>')
.appendTo($(column.footer()).empty())
.on("change", function () {
var val = $.fn.dataTable.util.escapeRegex($(this).val());
column
.search(val ? "^" + val + "$" : "", true, false)
.draw();
});
column
.data()
.unique()
.sort()
.each(function (d, j) {
select.append(
'<option value="' + d + '">' + d + "</option>"
);
});
});
}
};
let headerInputFilter = function (target, table, searchableColumns) {
if (
typeof searchableColumns != "undefined" &&
typeof target != "undefined" &&
typeof table != "undefined"
) {
$("#" + target + " thead tr")
.clone(true)
.addClass("filters")
.appendTo("#" + target + " thead");
var i = 0;
var api = table;
api.columns()
.eq(0)
.each(function (colIdx) {
if (
searchableColumns.includes(
$(api.column(colIdx).header()).index()
)
) {
var cell = $(".filters th").eq(
$(api.column(colIdx).header()).index()
);
var title = $(cell).text();
$(cell).html(
'<input style="width:100% !important" type="text" placeholder="' +
title +
'" />'
);
$(
"input",
$(".filters th").eq(
$(api.column(colIdx).header()).index()
)
)
.off("keyup change")
.on("keyup change", function (e) {
e.stopPropagation();
$(this).attr("title", $(this).val());
var regexr = "({search})";
var cursorPosition = this.selectionStart;
api.column(colIdx)
.search(
this.value != ""
? regexr.replace(
"{search}",
"(((" + this.value + ")))"
)
: "",
this.value != "",
this.value == ""
)
.draw();
$(this)
.focus()[0]
.setSelectionRange(
cursorPosition,
cursorPosition
);
});
} else {
return true;
}
});
}
};
let editorFormButtons = function (editor) {
if (typeof editor != "undefined") {
return [
{
extend: "create",
editor: editor,
formButtons: [
{
label: "Save",
fn: function () {
var that = this;
this.submit(function () {
that.close();
});
},
},
],
},
{
extend: "edit",
text: "Edit",
editor: editor,
formButtons: [
{
label: "Save & close",
fn: function () {
var that = this;
this.submit(function () {
that.close();
});
},
},
{
label: "Update",
fn: function () {
this.submit(function () {
editor.edit(
table.rows({ selected: true }).indexes()
);
});
},
},
],
},
{
extend: "remove",
editor: editor,
formButtons: [
{
label: "Delete",
fn: function () {
var that = this;
this.submit(function () {
that.close();
});
},
},
],
},
];
}
};
let inlineEdit = function (target, editor) {
if (typeof target != "undefined" && typeof editor != "undefined") {
$("#" + target + "").on(
"click",
"tbody td:not(.no-inline)",
function (e) {
if (
$(this).hasClass("editor-edit") ||
$(this).hasClass("control") ||
$(this).hasClass("select-checkbox") ||
$(this).hasClass("dataTables_empty")
) {
return;
}
editor.inline(this, {
submit: "allIfChanged",
});
}
);
}
};
module.exports = {
headerInputFilter,
footerSelectFilter,
editorFormButtons,
inlineEdit,
};
When I set server-side to false the custom functionalities I need works perfectly but I need these with server-side processing as it will significantly improve overall performance . I would appreciate any help and suggestion.
Regards,
Shovon Choudhury
I am using DataTables 1.10.12. I implemented it using MVC framwork. My problem is I have 25 columns in the table which I can accomodate on the same page if I do not have the sorting images in the . To remove them I have tried the following:
<table id="datatable-buttons-por" class="table table-striped table-bordered">
<thead style="font-size:smaller; background:none">
<tr>
And following
$(document).ready(function () {
var handleDataTableButtons = function () {
if ($("#datatable-buttons-por").length) {
$("#datatable-buttons-por").DataTable({
dom: "Bfrtip",
buttons: [
{
extend: "copy",
className: "btn-sm"
},
{
extend: "csv",
className: "btn-sm"
},
{
extend: "excel",
className: "btn-sm"
},
{
extend: "pdfHtml5",
className: "btn-sm"
},
{
extend: "print",
className: "btn-sm"
},
],
responsive: true
});
}
};
TableManageButtons = function () {
"use strict";
return {
init: function () {
handleDataTableButtons();
}
};
}();
var $datatable = $('#datatable-checkbox');
$datatable.dataTable({
'order': [[1, 'asc']],
'columnDefs': [
{ orderable: false, targets: [0] }
]
});
$datatable.on('draw.dt', function () {
$('input').iCheck({
checkboxClass: 'icheckbox_flat-green'
});
});
TableManageButtons.init();
//$('#datatable-buttons-por thead').css('background-image', 'none');
var table = $('#datatable-buttons-por').DataTable();
table.columns().every(function () {
var column = this;
var select = $('<select><option value=""></option></select>')
.appendTo($(column.footer()).empty())
.on('change', function () {
var val = $.fn.dataTable.util.escapeRegex(
$(this).val()
);
column
.search(val ? '^' + val + '$' : '', true, false)
.draw();
});
column.data().unique().sort().each(function (d, j) {
select.append('<option value="' + d + '">' + d + '</option>')
});
});
});
$('#datatable-buttons-por thead th').css('background-image', 'none');
in Javascript.
Seems like none of these working. What I am doing wrong here? By the way, I still want to keep my sorting functionality enabled.
You need to target the th not the thead
try:
$('#datatable-buttons-por thead th.sorting').css('background-image', 'none');
I currently have a DataTable that has data download buttons in format that I'm looking for:
$(document).ready(function() {
$('#dataTables-example').DataTable( {
dom: 'Bfrtip',
buttons: [
'copyHtml5',
'excelHtml5',
'csvHtml5',
'pdfHtml5'
]
} );
} );
However, I want to be able to filter columns with a dropdown menu in the footer - exactly like in the example in this link:
https://datatables.net/examples/api/multi_filter_select.html
The initialization code for that is:
$(document).ready(function() {
$('#dataTables-example').DataTable( {
initComplete: function () {
this.api().columns().every( function () {
var column = this;
var select = $('<select><option value=""></option></select>')
.appendTo( $(column.footer()).empty() )
.on( 'change', function () {
var val = $.fn.dataTable.util.escapeRegex(
$(this).val()
);
column
.search( val ? '^'+val+'$' : '', true, false )
.draw();
} );
column.data().unique().sort().each( function ( d, j ) {
select.append( '<option value="'+d+'">'+d+'</option>' )
} );
} );
}
} );
} );
What I want is to combine these two functionalities - column filter and data download options. I've tried moving around the button and dom snippet into the code above:
dom: 'Bfrtip',
buttons: [
'copyHtml5',
'excelHtml5',
'csvHtml5',
'pdfHtml5'
]
} );
But I've had no luck getting it to display correctly (or at all).
I had an engineering breakthrough and did the obvious thing, added the DOM settings before:
initComplete: function(){.......
And it worked.
Complete function:
$(document).ready(function() {
$('#dataTables-example').DataTable( {
dom: 'lBfrtip',
buttons: [
'copyHtml5',
'excelHtml5',
'csvHtml5',
'pdfHtml5'
],
initComplete: function () {
this.api().columns().every( function () {
var column = this;
var select = $('<select><option value=""></option></select>')
.appendTo( $(column.footer()).empty() )
.on( 'change', function () {
var val = $.fn.dataTable.util.escapeRegex(
$(this).val()
);
column
.search( val ? '^'+val+'$' : '', true, false )
.draw();
} );
column.data().unique().sort().each( function ( d, j ) {
select.append( '<option value="'+d+'">'+d+'</option>' )
} );
} );
}
});
});
I am doing column filtering by using this example as reference and this is what I am doing and it's working fine.
I have multiple columns so how can we implement it by using loop here?
$(document).ready(function() {
var table;
// DataTable
table = $('#example').dataTable({
"processing": true,
stateSave: true,
"deferRender": true, // to make the search fast
"dom": 'C<"clear">Rfltipr', // for column Re-odering and column visibilty.
"ajax": {
"url": "/my/example.so",
"type": "GET"
},
"columns": [{
"title": "name",
"data": "name",
"name": "name"
}, {
"title": "addeddate",
"data": "addeddate",
"name": "added date"
}]
});
table.columnFilter({
sPlaceHolder: "head:before",
aoColumns: [{
type: "text"
}, {
type: "date-range",
bRegex: true,
bSmart: true
}
}
]
});
$.datepicker.regional[""].dateFormat = 'yy-mm-dd';
$.datepicker.setDefaults($.datepicker.regional['']);
Moreover, here I need to write <th> tags also for all columns which is not good in case of multiple columns AS WELL. // second way to do it which is not suitable to do for date column Setup - add a text input to each cell
var noofcolumn= $('#example thead th').length;
colmn="";
for(i=0; i<noofcolumn; i++)
{
var title = $('#example thead th').eq( i ).text();
colmn+='<th><input type="text" placeholder="Search '+title+'" /></th>';
}
$('#example tfoot').html( colmn );
// Apply the search
table.columns().every( function ()
{
$('input', this.footer() ).on( 'keyup change', function () {
table
.column( $(this).parent().index()+':visible' )
.search( this.value )
.draw();
} );
});