I am using DataTable plugin. The examples in the linked page are great. But I have a problem.
In the example user may sort the datatable after doing a search. I successfully do this. But when I created a filter, the sorting is messed up.
This is the expected sequence:
Page shows all data in the datatable
User do a filter (Show data by some filter. Like by date, by status, by country etc)
Page show certain data with the searched filter
User may do a search using text to view less data
User may do sort by column
In my script, the code works until point 3. When user do a search the filtered data is reset to show all data(not-filtered)
How do I deal with this?
This is my table:
<table id="tbl_surat_all" class="table table-striped table-bordered table-hover dataTables-example" >
<thead>
<tr>
<th class='text-center' width="1%">No</th>
<th class="text-center" width="10%">ID Proyek</th>
</tr>
<tbody><!--Data collected from php--></tbody>
</thead>
<tbody>
The jQuery:
$('.dataTables-example').DataTable({
pageLength : 25,
responsive : true,
dom : '<"html5buttons"B>lTfgitp',
buttons : [
{extend: 'copy'},
{extend: 'csv', title : "list<?php echo date('d/m/Y'); ?>"},
{extend: 'excel', title : "list<?php echo date('d/m/Y'); ?>"},
{extend: 'pdf', title : "list<?php echo date('d/m/Y'); ?>"},
{extend: 'print',
customize: function (win){
$(win.document.body).addClass('white-bg');
$(win.document.body).css('font-size', '10px');
$(win.document.body).find('table').addClass('compact').css('font-size', 'inherit');
}
}
]
});
This this the filter do (It's ajax success call):
var row;
var no = 1;
$('#tbl_surat_all tbody tr').remove();
$.each(response, function(index, data) {
row = "<tr><td>"+ no++ +"</td><td>"+data.idproyek+"</td></tr>";
$('#tbl_surat_all tbody').append(row);
});
Note:
the conclusion is how do I copy the search behavior (default from the library) to my filter (my own created jquery) behavior?
If you look at the search api, you can either search on the table as shown.
var table = $('#example').DataTable();
// #myInput is a <input type="text"> element
$('#myInput').on( 'keyup', function () {
table.search( this.value ).draw();
} );
Or you can name your columns when you initialize the datatable and search each column for text and apply that to the datatable.
columns: [
{
name: 'colName',
data: 'colData',
type: 'date'
}
searching on the column would be
var col = table.columns('colname:name');
col.search('searchTerm');
table.draw();
Related
I've got two tables (table1,table2) that are structurally the same, but fed from different sources. Both tables share the class 'display' which I use to initialise the plugin for both tables. This works great for the most part, however the column filters select menu for table2 is duplicated on table1.
I've tried to fix this by using 'this' keyword to indicate a particular instance of the toolbar each of the filters need applying to, but not had much success.
The code that works is:
HTML:
<table id="table1" class="display table-striped table-borded table-hover" cellspacing="0" width="100%">
<thead>
<tr>
<th>Report Name</th>
<th>Year</th>
<th>Montly Snapshot</th>
</tr>
</thead>
<tfoot>
<tr>
<th>Date of Last Refresh --var from warehouse-- </th>
</tr>
</tfoot>
</table>
<table id="table2" class="display table-striped table-borded table-hover" cellspacing="0" width="100%">
<thead>
<tr>
<th>Report Name</th>
<th>Year</th>
<th>Montly Snapshot</th>
</tr>
</thead>
<tfoot>
<tr>
<th>Date of Last Refresh --var from warehouse-- </th>
</tr>
</tfoot>
</table>
JS:
//initialise data tables plugin and apply custom settings.
var reportstable = $('table.display').DataTable({
"sDom": '<"toolbar">Bfrtlp',
"searchCols": [
null, {
'sSearch': 'Current'
}
],
language: {
search: "_INPUT_",
searchPlaceholder: "Search for a Report..."
},
// create select form controls
initComplete: function() {
this.api().columns([1, 2]).every(function() {
var column = this;
var select = $('<select><option value=""></option></select>')
.appendTo($('.toolbar'))
.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>')
if ($('#info').css('display') == 'block') {
$("#reports_wrapper").css('display', 'none');
}
// add bootstrap classes and placeholder property to form controls to add style
$('.toolbar select').addClass('selectpicker');
$('.dt-button').addClass('btn btn-danger').removeClass('dt-button');
$('.toolbar select').attr('id', 'year');
$('#year').prop('title', 'Financial Year');
$("#year option:contains('Current')").remove();
$('.toolbar select:nth-of-type(2)').attr('id', 'month');
$('#month').prop('title', 'Monthy Snapshot');
$("#month option:contains('undefined')").remove();
});
});
},
// create clear filter button
buttons: [
{
text: 'Clear Filters',
action: function(e, dt, node, config) {
$('select').val('').selectpicker('refresh');
// set Current Year as default filter
reportstable
.search('')
.columns([1]).search('Current')
.columns([2]).search('')
.draw();
}
}
],
//hide specified columns
"columnDefs": [
{
"targets": [1],
"visible": false,
"searchable": true
}, {
"targets": [2],
"visible": false,
"searchable": true
}
]
});
I've updates your jsfiddle and created a new jsfiddle. It's now appending 2 select menus in both tables's wrapper div. I've found why it's appending 4 select menus instead of 2 on the table1's wrapper div. It's because of this code: .appendTo($('.toolbar')). When initComplete callback function is called for table1 there is only one div with class=toolbar, and when the initComplete callback function is called for table2 there is two div with class=toolbar, one in table1's wrapper div and one in table2's wrapper div. that's why on table2's initComplete callback function it append select menus to all divs with class=toolbar. We should rather append to the current table wrapper's div with class=toolbar.
I want to populate a Datatable with a dynamic column header and column data. I can populate dynamic column data successfully, but I can't achieve a dynamic column. I am using an array I get from a JSON AJAX request. My code is this:
<body>
<table id="example" class="display" cellspacing="0" width="100%" border="1"></table>
</body>
var JSONResult = '{"column1":"data1","column2":"data2","column3":"data3","columnN":"dataN"}';
var row_dtable = new Array();
var dtable_api = $('#example').dataTable();
$.each(JSONResult , function(key, value) {
row_dtable.push(value);
});
dtable_api.api().row.add(row_dtable).draw(false);
Thanks in advance.
Datatables doesn't have the ability to change it's structure once being created. You have to destroy it and then re-create with a new set of columns.
Additional reading: How to dynamically change Datatables multiple column headers using ajax and jquery without refreshing the webpage?
Ideally your JSONResult will always have the same columns and only data will be updated. For this the solution will be to create the columns once in the header of your table and then using the datatable API to add the data.
First you should change your table HTML like this, which shouldn't be a problem.
<body>
<table id="example" class="display" cellspacing="0" width="100%" border="1">
<thead>
<tr></tr>
</thead>
</table>
</body>
Then you create the headers through jQuery
var JSONResult = [{ "column1": "data1", "column2": "data2", "column3": "data3", "columnN": "dataN" },
{ "column1": "data1", "column2": "data2", "column3": "data3", "columnN": "dataN" }];
$.each(JSONResult[0], function (key, value) {
$('#example thead tr:first-child').append($('<th>', {
text: key
}));
});
And last, add the data to dataTable
var row_dtable = new Array();
var dtable_api = $('#example').dataTable();
$.each(JSONResult, function (i, l) {
$.each(l, function (key, value) {
console.log(key + " " + value);
row_dtable.push(value);
});
dtable_api.api().row.add(row_dtable).draw(false);
});
A user can search for people included in a database introducing the search terms in an input text.
I am using following Ajax script to show the database objects received from JSON:
<script type="text/javascript">
$(document).ready(function() {
// With JQuery
$("#ex6").slider();
$("#ex6").on("slide", function(slideEvt) {
$("#ex6SliderVal").text(slideEvt.value);
});
$('#keyword').on('input keyup change', function() {
var searchKeyword = $(this).val();
if (searchKeyword.length < 3) {
$('ul#content').empty()
}
if (searchKeyword.length >= 1) {
$.post('search.php', { keywords: searchKeyword }, function(data) {
$('#content').empty()
$('#content').append('<table class="table table-hover"><thead><tr><th>First Name</th><th>Last Name</th><th>Username</th></tr></thead><tbody>')
if (data == ""){
$('#content').append('No hay resultados para su búsqueda')
}
$.each(data, function() {
$('#content').append('<tr><td>'+this.nombre_doctor +'</td><td>'+ this.apellido1_doctor + '</td><td>'+ this.apellido2_doctor+'</td></tr>');
});
$('#content').append('</tbody></table>')
}, "json");
}
});
});
</script>
And this is the output when a user introduces a search term:
As you may see in the picture, the objects are not shown on the expected column.
What is wrong in the script?
When you call append with a string, jQuery constructs an object and appends that. In other words, append('<foo>') is really append($('<foo'>). The assumption in this code that append appends raw HTML is incorrect.
You want something like
var $table = $('<table class="table table-hover"><thead><tr><th>First Name</th><th>Last Name</th><th>Username</th></tr></thead></table>').appendTo('#content');
var $tbody = $('<tbody></tbody>').appendTo($table);
$.each(data, function() {
var $tr = $('<tr>').appendTo($tbody);
$('<td>').text(this.nombre_doctor).appendTo($tr);
$('<td>').text(this.apellido1_doctor).appendTo($tr);
$('<td>').text(this.apellido2_doctor).appendTo($tr);
});
// Nothing with </tbody></table> , those elements already exist
Note that your current code includes a significant vulnerability as it allows everybody who controls your data to inject arbitrary HTML and JavaScript into your website. The use of text avoids this.
You used a concate (+) function which packed all data into one column as a string. You should define 3 distinct columns to force a proper table layout.
<table width="100%" rules=groups border="0" cellspacing="0" cellpadding="0" class="table table-hover">
<colgroup>
<col width="33%" />
<col width="33%" />
<col width="33%" />
</colgroup>
Now you have a solid structure to insert your data, by column. The <th> will line up the way you have written the code.
Try building your table html as a string first, then use jquery's .html() to set it.
var htmlContents = "<table><tr><td>First column data</td><td>2nd column
data</td><td>etc</td></tr></table>";
$('#content').html(htmlContents);
That should do it.
I'm using this bootstrap-table. I'd like to nest one table into another.
$(document).ready(function() {
var t = [{
"id": "1",
"name": "john",
}, {
"id": "2",
"name": "ted"
}];
//TABLE 1
$('#summaryTable').bootstrapTable({
data: t,
detailFormatter: detailFormatter
});
function detailFormatter(index, row, element) {
$(element).html(row.name);
$(element).html(function() {
//I was thinking of putting the code here, but I don't know how to do it so it will work,
//except javascript, it needs to be put this html code <table id="detailTable"></table>
});
// return [
// ].join('');
}
//TABLE 2
var t2 = [{
"id": "1",
"shopping": "bike",
}, {
"id": "2",
"shopping": "car"
}];
$('#detailTable').bootstrapTable({
data: t2,
columns: [{
field: 'id',
title: 'id'
}, {
field: 'shopping',
title: 'Shopping detail'
}, {
field: 'status',
checkbox: true
}],
checkboxHeader: false
});
$('#detailTable').on('check.bs.table', function(e, row, $el) {
alert('check index: ' + row.shopping);
});
$('#detailTable').on('uncheck.bs.table', function(e, row, $el) {
alert('uncheck index: ' + row.shopping);
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-table/1.10.0/bootstrap-table.min.css" rel="stylesheet"/>
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.6/js/bootstrap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-table/1.10.0/bootstrap-table.min.js"></script>
<div class="container">
<p>TABLE 1</p>
<table id="summaryTable" data-detail-view="true">
<thead>
<tr>
<th data-field="id" data-align="center" data-width="20px">id</th>
<th data-field="name" data-align="center">Name</th>
</tr>
</thead>
</table>
<br>
<p>TABLE 2</p>
<table id="detailTable"></table>
</div>
Here is the link of my demo: fiddle
There are two tables. Table 1 has expandable rows and I want to put Table 2 into every row of table 1. There is this function called detailFormatter which does this and where you can return a string or render an element (I was playing with it, but I can't make it work). For this demo the table 1 is created with some html code and the table 2 uses only javascript, but there is this initiating div <table id="detailTable"></table> (it doesn't matter for me which way is done). So, the question is how to put the table 2 into table 1 with possibility of using its events (like check or uncheck checkbox) as the demo shows for table2? Later on, I'd like to use this event onExpandRow so when the user expands the row of table 1 it will get the data from a database and it'll fill out the table 2.
Well just clone your detailTable and put it in each row with detailFormatter as below:
function detailFormatter(index, row, element) {
$(element).html($('#detailTable').clone(true));
}
Now there will be duplicate id's created when you do clone, so you just remove it by changing its id as below:
function detailFormatter(index, row, element) {
$(element).html($('#detailTable').clone(true).attr('id',"tbl_"+row.id));
}
Also, you can hide the #detailTable since you are just having it to append it in another table and once you hide it you need to add show to cloned tables as all the properties will be copied to in clone(true) which can be done as below:
function detailFormatter(index, row, element) {
$(element).html($('#detailTable').clone(true).attr('id',"tbl_"+row.id).show());
}
//.....
//.....
//.....
//At the end
$("#detailTable").hide();
A complete DEMO
I found another way of nesting one table into another using (partly) dynamic table creation (referring to my posted question when using bootstrap-table).
var expandedRow = row.id;
$(element).html(
"<table id='detailTable"+expandedRow+"'><thead><tr><th data-field='id2' data-align='center' data-width='20px'>id2</th>" +
"<th data-field='shopping' data-align='center'>Shopping detail</th>" +
"<th data-field='status' data-checkbox='true'></th>" +
"</tr></thead></table>");
$('#detailTable'+expandedRow).bootstrapTable({
data: t2,
checkboxHeader: false
});
I think this way is more independent. There is no need to have one panel opened at the time. The events and methods seems to be working fine.
Full code here.
i'm new to datatable jquery plugin.
I got stuck with this for more than 2 days. I have a Json Data, i still cant load the table and i also want to assign first column to be id of the row
Here is html:
<table cellpadding="0" cellspacing="0" border="0" class="display"
id="accDetailTable">
<thead>
<tr>
<th>Currency</th>
<th>Current/Savings Account No.</th>
<th>Securities Account No.</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
and my initialization
var oTable=$('#accDetailTable').dataTable( {
"bProcessing": true,
"bServerSide": true,
"sAjaxSource": contextPath + "/user/investorAjax?method=getInvestorAccDetailList",
"iDeferLoading": 57,
} );
Return jsonData from server :
{"sEcho":1,"iColumns":4,"iTotalRecords":16,"iTotalDisplayRecords":16,
"aaData":
[{"DT_RowId":2032,"currency":1,"currentAccNo":"aa","secureAccNo":"aa"},
{"DT_RowId":2033,"currency":1,"currentAccNo":"111","secureAccNo":"111"},
{"DT_RowId":2034,"currency":1,"currentAccNo":"a","secureAccNo":"aa"},
]}
}
But it always hit :
DataTables warning (table id = 'accDetailTable'): Added data (size undefined) does not match known number of columns (3)
Your datatables is waiting for three entries per line and you give it four. In your table declaration (in html part) specify a new header cell <th> at the beginning of your row. You will put ids in it. Then after your dataTables initialization you can hide the first column using fnSetColumnVis(index, visibility) function :
oTable.fnSetColumnVis(0, false); //It will hide your first column
Doing that each row is containing his id (DT_RowId) but not displaying it.
It's kind of easy. Let's just do a tiny change, since you want the first column contains id, you may need to use fnRender, please check the api of datatables, I didn't add this part of code:
var oTable=$('#accDetailTable').dataTable({
"bProcessing": true,
"bServerSide": true,
"sAjaxSource": contextPath + "/user/investorAjax?method=getInvestorAccDetailList",
"aoColumns":[
{"mDataProp":"currency"},
{"mDataProp":"currentAccNo"},
{"mDataProp":"secureAccNo"}
]
});