Reputation: 1938
Is it possible to combine the Select Inputs
and the Text Inputs
? I use DataTables on several tables, always the same initialization. I would like to chose the column for the Select Inputs
by the column header since the column that I want the select list on is not always in the same position. Then all the others I want to have the Text Inputs
. This way I'll have one column that has the Select Inputs
and all others that have the Text Inputs
.
I have been able to implement the different Select and Text Inputs from these two examples. But I'm not good enough with jquery and javascript to figure out how to select the right column for the Select Input
and have all the others be Text Inputs
. The tables that I use can be anywhere from 3 columns to 75+ columns. And I want to select the column by the header name for the Select input.
And on top of all of this, is there a way to make the Select Input
a MultiSelect Input? I am having it a selector for the state and would like to be able to select multiple states at once.
Here are the two different ways I've used for the Select
and Text
input:
initComplete: function ()
{
this.api().columns([1]).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()
);
var strVal = val.replace("<div class='Scrollable'>", '');
strVal = strVal.replace("<\/div>", '');
column
.search(strVal ? /*'^' +*/ strVal /*+ '$'*/ : '', true, false)
.draw();
});
column.data().unique().sort().each(function (d, j)
{
var strValue = d.replace("<div class='Scrollable'>", '');
strValue = strValue.replace("<\/div>", '');
select.append('<option value="' + strValue + '">' + strValue + '</option>')
});
});
}
,
initComplete: function ()
{
var api = this.api();
// Apply the search
api.columns().every(function ()
{
var that = this;
$('input', this.footer()).on('keyup change', function ()
{
if (that.search() !== this.value)
{
that
.search(this.value)
.draw();
}
});
});
}
EIDT
Using @Gyrocode's suggestion from below I now have this:
initComplete: function ()
{
var api = this.api();
// Apply the search
api.columns('.dt-filter-text').every(function ()
{
var that = this;
$('input', this.footer()).on('keyup change', function ()
{
if (that.search() !== this.value)
{
that
.search(this.value)
.draw();
}
});
});
api.columns('.dt-filter-select').every(function ()
{
var column = this;
var select = $('<select><option value=""></option></select>')
.appendTo($(column.footer()).empty())
.on('change', function ()
{
var val = $.fn.dataTable.util.excapeRegex(
$(this).val()
);
var strVal = val.replace("<div class='Scrollable'>", "");
strVal = strVal.replace("</div>", '');
column
.search(strVal ? /*'^' +*/strVal /*+ '$'*/ : '', true, false)
.draw();
});
column.data().unique().sort().each(function (d, J)
{
var strValue = d.replace("<div class='Scrollable'>", '');
strValue = strValue.replace("</div>", '');
select.append('<option value="' + strValue + '">' + strValue + '</option>')
});
});
}
This almost works. When I select a value from the selector in the State column it doesn't search. I'm sure I'm missing something obvious, but I don't know what.
Also, it is not getting all the states, only the ones on the first page. Is there a way to get all the states or perhaps to have an array that will hold all the values that I need since the states are not likly to change?
Upvotes: 1
Views: 4955
Reputation: 41
I've got it working. Just be sure to add classes to the header, like so:
<thead>
<tr>
<th class="dt-filter-text">Name</th>
<th class="dt-filter-select">Position</th>
<th class="dt-filter-select">Office</th>
<th class="dt-filter-text">Age</th>
<th class="dt-filter-text">Start date</th>
<th class="dt-filter-text">Salary</th>
</tr>
</thead>
<tfoot>
<tr>
<th>Name</th>
<th>Position</th>
<th>Office</th>
<th>Age</th>
<th>Start date</th>
<th>Salary</th>
</tr>
</tfoot>
JavaScript:
$(document).ready(function() {
// DataTable
$('#table').DataTable({
initComplete: function () {
//Apply select search
this.api().columns('.dt-filter-select').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>')
});
});
//Apply text search
this.api().columns('.dt-filter-text').every(function () {
var title = $(this.footer()).text();
$(this.footer()).html('<input type="text" placeholder="Search '+title+'" />');
var that = this;
$('input',this.footer()).on('keyup change', function () {
if (that.search() !== this.value) {
that
.search(this.value)
.draw();
}
});
});
}
});
});
Add this to CSS if you want to place the footer directly below the header:
#table tfoot {
display: table-header-group;
}
Upvotes: 4
Reputation: 58920
You need to specify column indexes for columns()
API method to target specific columns.
For example:
initComplete: function ()
{
// Initialize dropdown filter in second column
this.api().columns([1]).every(function ()
{
// ... skipped ...
});
// Initialize text filter in first, third and fourth column
this.api().columns([0, 2, 3]).every(function ()
{
// ... skipped ...
});
}
However, instead of dealing with column indexes, I would assign a class name to each th
element where you want a text box (dt-filter-text
) or dropdown (dt-filter-select
). Then you can supply a selector to columns()
API method, for example columns('.dt-filter-text')
or columns('.dt-filter-select')
.
Upvotes: 1