jQuery DataTables - Child Rows and "Undefined is Not a Function" - javascript

I'm working to add child rows to a data table and am getting a "TypeError: undefined is not a function" for a line of code that works perfectly on a different table and page. Any ideas?
HTML:
<div class="table-responsive">
<h2 class="sub-header">Account Users <span class="glyphicon glyphicon-question-sign"></span></h2>
<table id="users_table" class="table table-striped embedded_table">
<thead>
<tr class="text-center">
<th></th>
<th>User Name</th>
<th>Full Name</th>
<th>User Type</th>
<th>Assigned Device</th>
<th>Date Added</th>
<th>Action</th>
</tr>
</thead>
</table>
</div>
Javascript/jQuery:
<script>
function format ( d ) {
var html = '<table id="child_table" class="text-right" cellpadding="5" cellspacing="0" border="0" style="padding-left:50px;">'+
'<tr>'+
'<td>Email Address:</td>'+
'<td>'+ d.email_address +'</td>'+
'<td>Time Zone:</td>'+
'<td>'+ d.timezone +'</td>'+
'</tr>'+
'<tr>'+
'<td>Create Date:</td>'+
'<td>'+ d.create_date +'</td>'+
'<td>Last Login:</td>'+
'<td>'+ d.last_login +'</td>'+
'</tr>'+
'</table>';
return html;
}
$(document).ready(function() {
username = "<?php echo($_SESSION["username"]); ?>";
userType = "<?php echo($_SESSION["user_type"]); ?>";
var table = $('#users_table').dataTable({
order: [1, 'asc'],
"ajax": {
"url": "/s/user_data.php",
"dataSrc" : ""
},
"language": {
"search": "Search: "
},
"columns": [
{"data": null, "class": "details-control", "orderable": false, "defaultContent": "", "width": "2%"},
{"data": "username", "name": "username", "width": "20%"},
{"data": "fullName", "name": "fullName", "width": "20%"},
{"data": "type", "name": "type", "width": "15%"},
{"data": "cal_color", "name": "cal_color", "width": "15%"},
{"data": "create_date", "type": "date", "name": "create_date", "visible": false},
{"data": "time_zone", "name": "time_zone", "visible": false},
{"data": "last_login", "type": "date", "name": "last_login", "visible": false},
{"data": "email_address", "name": "email_address", "visible": false},
{"data": "uid", "name": "uid", "visible": false}
]
});
// Add event listener for opening and closing details
$('#users_table').find('tbody').on('click', 'td.details-control', function () {
var tr = $(this).closest('tr');
var td = $(this).closest('td');
var row = table.row(tr);
console.log(tr);
console.log(td);
console.log(row);
if(row.child.isShown())
{
// This row is already open - close it
row.child.hide();
tr.removeClass('shown');
td.removeClass('shown');
}
else
{
// Open this row
row.child(format(row.data())).show();
tr.addClass('shown');
td.addClass('shown');
}
});
});
The line of code that generates the error is as follows. It's under the comment "Add event listener for opening and closing details" in the bottom third of the script.
var row = table.row(tr);
Like I said, I'm using the same listener on another table and this line isn't an issue there. I've checked my punctuation multiple times and don't see any missing commas, semicolons, or quotes. You can see that I have 3 lines writing to the console log. Here's what I get if I comment out the offending line:
[tr.even, prevObject: n.fn.init[1], context: td.details-control, jquery: "1.11.0", constructor: function, selector: ""…]
[td.details-control, prevObject: n.fn.init[1], context: td.details-control, jquery: "1.11.0", constructor: function, selector: ""…]
I'm not a strong javascript or jQuery developer. All comments and suggestions are welcome.
Thanks.

I think you should replace
var table = $('#users_table').dataTable({...
by
var table = $('#users_table').DataTable({
The difference? Datable with a capital "D". Otherwise, you can't use the function table.row()
From the manual (https://datatables.net/manual/api), you can see:
It is important to note the difference between $( selector ).DataTable() and $( selector ).dataTable(). The former returns a DataTables API instance, while the latter returns a jQueryJS object. An api() method is added to the jQuery object so you can easily access the API, but the jQuery object can be useful for manipulating the table node, as you would with any other jQuery instance (such as using addClass(), etc.).

Related

How to make childrow always open without getting performance hit

I have a Datatable with childrow:
$(document).ready(function () {
var table = $('#example').DataTable({
ajax: 'static/ajax/data/data.json',
columns: [
{
className: 'dt-control',
orderable: false,
data: null,
defaultContent: '',
},
{ data: 'Value1' },
{ data: 'Value2' },
{ data: 'Value3' },
],
order: [[1, 'asc']],
});
// Add event listener for opening and closing details
$('#example tbody').on('click', 'td.dt-control', function () {
var tr = $(this).closest('tr');
var row = table.row(tr);
if (row.child.isShown()) {
// This row is already open - close it
row.child.hide();
tr.removeClass('shown');
} else {
// Open this row
row.child(format(row.data())).show();
tr.addClass('shown');
}
});
How can I make the child row always open without a performance hit and remove the default green cross? I'm using ajax as a data source.
To create a DataTable with all child data always displayed, you can take the standard approach (for example, using the demo shown here), and then make the following changes:
1 - remove the first (empty) column from the header <th></th> - and also from the footer if needed.
2 - remove the first body column also, as defined in the DataTable itself:
{
className: 'dt-control',
orderable: false,
data: null,
defaultContent: '',
},
The above 2 changes ensure there still the same number of body columns as there are header (and footer) columns.
3 - remove the event listener code (it is no longer needed):
$('#example tbody').on('click', 'td.dt-control', function () { ... });
4 - Add an initComplete section to the DataTable:
initComplete: function( settings, json ) {
this.api().rows().every( function () {
this.child( format(this.data()) ).show();
});
}
The following example shows the above approach, but it uses a small JavaScript-sourced data set instead of Ajax data.
That does not make a difference to the above steps. Just replace my data: dataSet, option with your ajax option.
var dataSet = [
{
"id": "1",
"name": "Tiger Nixon",
"position": "System Architect",
"salary": "$320,800",
"start_date": "2011/04/25",
"office": "Zürich",
"extn": "5421"
},
{
"id": "57",
"name": "Donna Snider",
"position": "Customer Support",
"salary": "$112,000",
"start_date": "2011/01/25",
"office": "New York",
"extn": "4226"
}
];
/* Formatting function for row details - modify as you need */
function format ( d ) {
// `d` is the original data object for the row
return '<table class="cell-border" cellpadding="5" cellspacing="0" border="0" style="padding-left:50px;">'+
'<tr>'+
'<td>Full name:</td>'+
'<td>'+d.name+'</td>'+
'</tr>'+
'<tr>'+
'<td>Extension number:</td>'+
'<td>'+d.extn+'</td>'+
'</tr>'+
'<tr>'+
'<td>Extra info:</td>'+
'<td>And any further details here (images etc)...</td>'+
'</tr>'+
'</table>';
}
$(document).ready(function() {
var table = $('#example').DataTable( {
data: dataSet,
columns: [
{ data: "name" },
{ data: "position" },
{ data: "office" },
{ data: "salary" }
],
initComplete: function( settings, json ) {
this.api().rows().every( function () {
this.child( format(this.data()) ).show();
});
}
} );
} );
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<title>Demo</title>
<script src="https://code.jquery.com/jquery-3.5.1.js"></script>
<script src="https://cdn.datatables.net/1.10.22/js/jquery.dataTables.js"></script>
<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/1.10.22/css/jquery.dataTables.css">
<link rel="stylesheet" type="text/css" href="https://datatables.net/media/css/site-examples.css">
</head>
<body>
<div style="margin: 20px;">
<table id="example" class="display dataTable cell-border" style="width:100%">
<thead>
<tr>
<th>Name</th>
<th>Position</th>
<th>Office</th>
<th>Salary</th>
</tr>
</thead>
</table>
</div>
</body>
</html>

How to replace standard bootstrap table with dataTables in jQuery?

I have tried and searching lot of solution but not solve my problem, even at dataTables website. The problem is how to display nested array in json using DataTables? Fo example below, How if I just want to display l3_id: "1" data only.
I try to understand this link but not really understand. Example
There is no error at console and network tab.
DataTable not appear, including dataTables features such as search box, pagination. (The CDN/library has been imported)
JSON
{
"data": [
{
"project_id": "1",
"l1_task": [
{
"l1_id": "1",
"l2_task": [
{
"l2_id": "1",
"l3_task": [
{
"l3_id": "1",
"l3_name": "My name"
}
]
}
]
}
]
}
]
}
JS (I am applying HTML in JS)
"<table id='Layer3Table' class='table dt-responsive nowrap' style='width:100%'>"+
"<thead>"+
"<tr>"+
"<th class='text-center'>ID</th>"+
"<th class='text-center'>Activity Name</th>"+
"</tr>"+
"</thead>"+
"</table>"+
$('#Layer3Table').DataTable({
ajax: {
url: url_project_detail",
dataSrc : "data"
},
columns: [
{ data : "l1_task.0.l2_task.0.l3_task.0.l3_id" },
{ data : "l1_task.0.l2_task.0.l3_task.0.l3_name" },
],
});
Either define your table, including all tbody content in HTML, then use DataTables to enable the search etc features. If you do it this way you don't need to set the url or columns (although you can still set other options).
$('#Layer3Table').DataTable();
Or if you want to make use of the url and column features, create the basic table structure in HTML
<table id='Layer3Table' class='table dt-responsive nowrap' style='width:100%'>
<thead>
<tr>
<th class='text-center'>Project ID</th>
<th class='text-center'>Project Name</th>
<th class='text-center'>Project Description</th>
<th class='text-center'>Project Status</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
Then set up your DataTable separately in JavaScript.
$('#Layer3Table').DataTable( {
ajax: {
url: url_project_detail,
crossDomain : true,
type : "POST",
cache : false,
dataType : "json",
contentType: "application/json",
dataSrc : "data",
},
columns: [
{ data : "l3_id", "className": "text-center" },
{ data : "l3_name", "className": "text-center" },
{ data : "l3_description", "className": "text-center" },
{ data : "l3_status", "className": "text-center" }
],
});
What you appear to be doing is looping over your results and creating a DataTable for each of them, which is why it doesn't understand.

How to search child row content

I would like this demo to work with the filter, not removing entries whose children have the data that you are filtering for.
E.g. in the example if you filter for 5407 Airi Satou does not get deleted and maybe even the child data gets expanded.
HTML and JS
/* Formatting function for row details - modify as you need */
function format ( d ) {
// `d` is the original data object for the row
return '<div class="slider">'+
'<table cellpadding="5" cellspacing="0" border="0" style="padding-left:50px;">'+
'<tr>'+
'<td>Full name:</td>'+
'<td>'+d.name+'</td>'+
'</tr>'+
'<tr>'+
'<td>Extension number:</td>'+
'<td>'+d.extn+'</td>'+
'</tr>'+
'<tr>'+
'<td>Extra info:</td>'+
'<td>And any further details here (images etc)...</td>'+
'</tr>'+
'</table>'+
'</div>';
}
$(document).ready(function() {
var table = $('#example').DataTable( {
"ajax": "/examples/ajax/data/objects.txt",
"columns": [
{
"class": 'details-control',
"orderable": false,
"data": null,
"defaultContent": ''
},
{ "data": "name" },
{ "data": "position" },
{ "data": "office" },
{ "data": "salary" }
],
"order": [[1, 'asc']]
} );
// Add event listener for opening and closing details
$('#example tbody').on('click', 'td.details-control', function () {
var tr = $(this).closest('tr');
var row = table.row( tr );
if ( row.child.isShown() ) {
// This row is already open - close it
$('div.slider', row.child()).slideUp( function () {
row.child.hide();
tr.removeClass('shown');
} );
}
else {
// Open this row
row.child( format(row.data()), 'no-padding' ).show();
tr.addClass('shown');
$('div.slider', row.child()).slideDown();
}
} );
} );
CSS
td.details-control {
background: url('/examples/resources/details_open.png') no-repeat center center;
cursor: pointer;
}
tr.shown td.details-control {
background: url('/examples/resources/details_close.png') no-repeat center center;
}
div.slider {
display: none;
}
table.dataTable tbody td.no-padding {
padding: 0;
}
SOLUTION
In order for jQuery DataTables to search child rows you need to add data displayed in the child rows to the main table as hidden columns.
For example, you can add hidden column for extn data property using columns.visible option as shown below:
JavaScript:
"columns": [
{
"class": 'details-control',
"orderable": false,
"data": null,
"defaultContent": ''
},
{ "data": "name" },
{ "data": "position" },
{ "data": "office" },
{ "data": "salary" },
{ "data": "extn", "visible": false }
],
HTML:
<thead>
<tr>
<th></th>
<th>Name</th>
<th>Position</th>
<th>Office</th>
<th>Salary</th>
<th>Extn.</th>
</tr>
</thead>
DEMO
See this jsFiddle for code and demonstration.

Populating a DataTable with JSON, need to render a hyperlink in one column with a value found in a different JSON field

I have a sample json object with data:
[
{
"id": 1,
"title": "Fred",
"author": "Flintstone"
}, {
"id": 2,
"title": "Fred",
"author": "Flintstone"
}, {
"id": 3,
"title": "Fred",
"author": "Flintstone"
}.....
HTML
<table class="table" id="tblRunbook">
<thead>
<tr>
<th width="60px">ID</th>
<th width="300px">Title</th>
<th width="200px">Author</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
JavaScript:
$(document).ready(function() {
$('#tblRunbook').dataTable({
<!-- Retrieve a static json file, you could also have a URL to a controller method. -->
"sAjaxSource" : "/getRunbooks",
"sAjaxDataProp": "",
<!-- Indicate to dataTable what the field names are we want, in the order we want them in the table. -->
"aoColumns": [
{"data": "id"},
{"data": "title",
"render": function ( data, type, row, meta ) {
return '<a href="runbook?rbID=" + data.id + '>' + data + '</a>';}
},
{"data": "author"}
]
});
});
The column with ID will be hidden, but I want to make the link runbook?rbID = ID. I would like to access the previous field in the JSON object, in this case, "data" : "id" and set it inside the second field where the function returns '<a href="runbook?rbID=" + data.id + '>', where data.id is the ID.
I was able to find a work-around.
var runbookID;
"aoColumns": [
{"data": function(data, type, row, meta){
runbookID = data.id;
return data.id;}
},
{"data": "title",
"render": function ( data, type, row, meta ) {
return "<a href='runbook?rbID=" + runbookID + "'>" + data + '</a>';}
},
{"data": "author"}
]

how to get the inner html value from Datatable cell

I am newbie to DataTable. here I am trying to get the of first cell value of a row when I click the viewlink associated with the row, instead of the value I am getting [object object].
heres my code
$(document).ready(function() {
// Delete a record
$('#example').on('click', 'a.editor_view', function (e) {
e.preventDefault();
var rowIndex = oTable.fnGetPosition( $(this).closest('tr')[0] );
aData = oTable.fnGetData($(this).parents('tr')[0]);
alert(aData);
} );
// DataTables init
var oTable=$('#example').dataTable( {
"sDom": "Tfrtip",
"sAjaxSource": "php/browsers.php",
"aoColumns": [
{ "mData": "browser" },
{ "mData": "engine" },
{ "mData": "platform" },
{ "mData": "grade", "sClass": "center" },
{
"mData": null,
"sClass": "center",
"sDefaultContent": 'view / Delete'
}
]
} );
} );
HTML Table:
<table cellpadding="0" cellspacing="0" border="0" class="display" id="example" width="100%">
<thead>
<tr>
<th width="30%">Browser</th>
<th width="20%">Rendering engine</th>
<th width="20%">Platform(s)</th>
<th width="14%">CSS grade</th>
<th width="16%">Admin</th>
</tr>
</thead>
<tfoot>
<tr>
<th>Browser</th>
<th>Rendering engine</th>
<th>Platform(s)</th>
<th>CSS grade</th>
<th>Admin</th>
</tr>
</tfoot>
Now when I Click on the view I need to Navigate to another page with the id like
view.php?id=125
Thank you
$('#example').on('click', 'a.editor_view', function (e) {
e.preventDefault();
var rowIndex = oTable.fnGetPosition( $(this).closest('tr')[0] );
aData = oTable.fnGetData(rowIndex,0);
alert(aData);
} );
From the api docs:
fnGetData
Input parameters:
{int|node}: A TR row node, TD/TH cell node or an integer. If given as a TR node then the data source for the whole row will be returned. If given as a TD/TH cell node then iCol will be automatically calculated and the data for the cell returned. If given as an integer, then this is treated as the aoData internal data index for the row (see fnGetPosition) and the data for that row used.
{int}: Optional column index that you want the data of.
Assuming your first row is your id, would you want to include the links in your dataTable initializer like this?
$(document).ready(function () {
var oTable = $('#example').dataTable({
"aoColumnDefs": [{
"fnRender": function (oObj) {
var id = oObj.aData[0];
var links = [
'View',
'Delete'];
return links.join(' / ');
},
"sClass": "center",
"aTargets": [4]
}, {
"sClass": "center",
"aTargets": [3]
}]
});
});
see: http://jsfiddle.net/9De6w/

Categories