Datatable foreach detail/child row - javascript

I want to display foreach child row datatable
lets say I have ajax data like this
"data": [
{
"date" : "1/17/2016",
"supplier" : "supplier1",
"total" : "$10",
"payment" : "Cash",
"product" : Array[2]
0: "product1"
1: "product2"
"price" : Array[2]
0: "$5"
1: "$5"
},
{
"date" : "2/1/2016",
"supplier" : "supplier2",
"total" : "$3",
"payment" : "Cash",
"product" : Array[1]
0: "product1"
"price" : Array[1]
0: "$3"
},
{
"date" : "1/17/2016",
"supplier" : "supplier3",
"total" : "$15",
"payment" : "Cash",
"product" : Array[3]
0: "product1"
1: "product2"
2: "product3"
"price" : Array[2]
0: "$3"
1: "$5"
2: "$7"
},
I wanna create datatable child row for product & price array following link here
I only edit script in function format to meet my need like this
function format ( d ) {
// `d` is the original data object for the row
return '<table class="table table-border table-hover">'+
'<tr>'+
'<td>Product</td>'+
'<td>Price</td>'+
'</tr>' +
'<?php
$loop = 5;
echo $loop; <-- here
for ($i=0; $i<$loop; $i++) {
echo "<tr><td>'+d.product['$i']+'</td> <td>'+d.price['$i']+'</tr>";
} ?>' +
'</table>';
}
it's run quite well...I can display data like i want..but i must define $loop manual...
I tried using $loop = "'+d.product.length+'"
when i echo that var in php it's display real value
(say i have 3 array in product it's display 3 too)
but somehow when it's enter for section it's like $loop become 0
because not display anyrow (if i set condition to $i<=$loop it's dispaly one row detail in every row parents)
i found something weird too
$loop = "'+d.product_.length+'" . "'+d.product_.length+'";
echo $loop ==> 33 (say if product array count is 3)
but if I change it to sum it's result 0
$loop = "'+d.product_.length+'" + "'+d.product_.length+'";
echo $loop ==> 0 (say if product array count is 3 too)
how to solve it, so i can know how many looping should my script do

You don't really need php here to append your extra table with a loop, rather you can use jquery's $.each.. You just need to construct your table body structure prior to append as below:
/* Formatting function for row details - modify as you need */
function format ( d ) {
console.log(d.product);
var trs=''; //just a variable to construct
$.each($(d.product),function(key,value){
trs+='<tr><td>'+value+'</td><td>'+d.price[key]+'</td></tr>';
//loop through each product and append it to trs and am hoping that number of price
//values in array will be equal to number of products
})
// `d` is the original data object for the row
return '<table class="table table-border table-hover">'+
'<thead>'+
'<th>Product</th>'+
'<th>Price</th>'+
'</thead><tbody>'
+ trs +
'</tbody></table>';
}
$(document).ready(function() {
var table = $('#example').DataTable({
"ajax": 'https://raw.githubusercontent.com/kshkrao3/JsonFileSample/master/Employees.json',
"columns": [
{
"class": 'details-control',
"orderable": false,
"data": null,
"defaultContent": ''
},
{ "data": "date"},
{ "data": "supplier"},
{ "data": "total"},
{ "data": "payment"}
]
});
// 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
row.child.hide();
tr.removeClass('shown');
}
else {
// Open this row
row.child( format(row.data()) ).show();
tr.addClass('shown');
}
});
});
Note : There was an error in your click event.. You were trying dTable.row in the event where as it has to be table.row since you are holding reference in table variable.
DEMO

Related

Jquery Datatables : How to get row.data when click the the button in one column?

[![enter image description here][1]][1]i have a nested table , I want to having button to generate the row data to info.php by post method (looks like info.php?user = data[0] & key2 = data2) in one column for each row ,
I have one button but I need one button and perform some MySql when they are clicked to get the row data .
when click the button will get to every columns data in the row and post these data to info.php and view in popup window,
How can I perform post the row data in the nested datatable to other php using the button?
my code
click the button ,cannot get the row data ?
$('#example tbody').on( 'click', 'button', function () {
var index = $(this).closest('tr').index();
var data = table.row( $(this).parents('tr') ).data();
alert("References is "+ data[0] +"and section is "+ data[ 1 ]+ " and Stature Titles is "+data[2] );
} );
-UPDATED
just add class for button class='button-info'
columns:[
{ data:'name' },
{ data:'position' },
{ data:'salary' },
{
"targets": -1,
"data": null,
"defaultContent": "<button class='button-info'>Click Me!</button>"
}
]
first assign index value for every parent row
$("table tbody tr").each(function(index) {
$(this).attr('index', index);
})
then add new event for click event of that button and get the parent tr index
just get the index of your selected parent row using data attribute "index" added above
var parent = $(this).closest('table').parents('tr').index();
var parentIndex = $('tbody tr:nth-child('+(parent)+')').attr('index');
and to get your current row in nested data
var index = $(this).closest('tr').index();
so this is the final
$('table').on( 'click', 'td .button-info', function () {
var parent = $(this).closest('table').parents('tr').index();
var parentIndex = $('tbody tr:nth-child('+(parent)+')').attr('index');
var currentIndex = $(this).closest('tr').index();
var data = sections[parentIndex][currentIndex];
console.log(data);
return;
window.open("/info.php?name=" + data.name + "&sal=" + data.salary);
} );
See this updated JSFiddle

Inline editing - save new values on button click

I have following code for jQuery DataTables:
Contact.DataTable = $('#otable').DataTable( {
"ajax": {
"url" : '/Contact/' + Contact.id,
"dataSrc": function(check) {
return check.data;
},
},
"responsive": true,
"columns": [
{ "data": "id"},
{ "data": "category", "sClass": "category" },
{ "data": "name", "sClass": "name" },
{ "data": "lname" },
{
"render": function ( data, type, method, meta ) {
return Contact.saveContact(method);
}
},
]
} );
Datatable - dropdown - inline edit:
$('#otable tbody').on('click', '.category', function () { //second column
var row = this.parentElement;
if(!$('#otable').hasClass("editing")){
$('#otable').addClass("editing");
var data = Contact.DataTable.row(row).data();
var $row = $(row);
var thiscategory = $row.find("td:nth-child(2)");
var thiscategoryText = thiscategory.text();
thiscategory.empty().append($("<select></select>",{
"id":"category" + data[0],
"class":"in_edit"
}).append(function(){
var options = [];
$.each(Categories, function(key, value){
options.push($("<option></option>",{
"text":value,
"value":value
}))
})
return options;
}));
$("#category" + data[0]).val(thiscategoryText)
}
})
;
For changing values in dropdown
$('#otable tbody').on("change", ".in_edit", function(){ //Inline editing
var val = $(this).val();
$(this).parent("td").empty().text(val);
$('#otable').removeClass("editing");
});
Below code for saving new values(after inline edit) while clicking save:
$('#divsave').on("click", ".saveContact", function() {
var data = Contact.DataTable.row($(this).closest('tr')).data();
// Here I have to get new values after inline editing - but getting old values
});
My problem is : while clicking edit, in 'data', I am getting old values in the row of datatable, not the modified value after inline edit
datatable view - 1:
datatable - dropdown in column:
datatable after inline editing:
What I need: Save modified row while clicking 'save' image - currently it saves older value before inline editing(datatable view - 1)
When using dataTables it is generally a very bad idea to manipulate the DOM <table> or any content by "hand" - you should always go through the dataTables API.
Thats why you are getting "old values" - you have manipulated the content of the <table>, or so it seems - dataTables are not aware of those changes.
In a perfect world you should refactor the setup completely (i.e to use the API) but I guess you can solve the issue by using invalidate() on the row being changed in order to refresh the dataTables internals :
$('#otable tbody').on("change", ".in_edit", function(){ //Inline editing
var val = $(this).val();
$(this).parent("td").empty().text(val);
//add this line to refresh the dataTables internals
Contact.DataTable.row($(this).parent("tr")).invalidate();
//
$('#otable').removeClass("editing");
});

Dynamic dropdown list using JavaScript object

I want to make a dynamic drop-down list based on a JavaScript object like this:
var EXERCISE_OBJ = {
"title" : {
"name" : "Exercise_Name",
"category" : "Pronunciation",
"type":"Multiple Choice",
},
"title2" : {
"name" : "Exercise_Name2",
"category" : "Spelling",
"type":"Crossword",
},
"title3" : {
"name" : "Exercise_Name3",
"category" : "Spelling",
"type":"Multiple Choice",
},
"title4" : {
"name" : "Exercise_Name4",
"category" : "Grammar",
"type":"Wordsearch",
},
}
I want a drop-down list enlisting all the categories and another one displaying all the exercise titles from each category.. How can I output it?
Please try this:
Create div with id test. <div id="test"></div>
var exercise_select = "<select name='exc'>";
var category_select = "<select name='cate'>";
$.each(EXERCISE_OBJ, function() {
var name = this.name;
var category = this.category;
exercise_select += "<option value='"+name+"'>"+name+"</option>";
category_select += "<option value='"+category+"'>"+category+"</option>";
});
exercise_select += "</select>"; category_select += "</select>";
$("#test").append(exercise_select); $("#test").append(category_select);

Pulling parts of JSON out to display them in a list

I have the following JSON:
var questions = {
section: {
"1": question: {
"1": {
"id" : "1a",
"title": "This is question1a"
},
"2": {
"id" : "1b",
"title": "This is question2a"
}
},
"2": question: {
"1": {
"id" : "2a",
"title": "This is question1a"
},
"2": {
"id" : "2b",
"title": "This is question2a"
}
}
}
};
NOTE: JSON changed based on the answers below to support the question better as the original JSON was badly formatted and how it works with the for loop below.
The full JSON will have 8 sections and each section will contain 15 questions.
The idea is that the JS code will read what section to pull out and then one by one pull out the questions from the list. On first load it will pull out the first question and then when the user clicks on of the buttons either option A or B it will then load in the next question until all questions have been pulled and then do a callback.
When the button in the appended list item is clicked it will then add it to the list below called responses with the answer the user gave as a span tag.
This is what I have so far:
function loadQuestion( $section ) {
$.getJSON('questions.json', function (data) {
for (var i = 0; i < data.length; i++) {
var item = data[i];
if (item === $section) {
$('#questions').append('<li id="' + item.section.questions.question.id + '">' + item.section.questions.question.title + ' <button class="btn" data-response="a">A</button><button class="btn" data-response="b">B</button></li>');
}
}
});
}
function addResponse( $id, $title, $response ) {
$('#responses').append('<li id="'+$id+'">'+$title+' <span>'+$response+'</span></li>');
}
$(document).ready(function() {
// should load the first question from the passed section
loadQuestion( $('.section').data('section') );
// add the response to the list and then load in the next question
$('button.btn').live('click', function() {
$id = $(this).parents('li').attr('id');
$title = $(this).parents('li').html();
$response = $(this).data('response');
addResponse( $id, $title, $response );
loadQuestion ( $('.section').data('section') );
});
});
and the HTML for the page (each page is separate HTML page):
<div class="section" data-section="1">
<ul id="questions"></ul>
<ul id="responses"></ul>
</div>
I've become stuck and confused by how to get only the first question from a section and then load in each question consecutively for that section until all have been called and then do a callback to show the section has been completed.
Thanks
Do not have multiple id's in html called "section."
Do not have multiple keys in your JSON on the same level called "section". Keys in JSON on the same level should be unique just as if you are thinking about a key-value hash system. Then you'll actually be able to find the keys. Duplicate JSON keys on the same level is not valid.
One solution can be section1, section2, etc. instead of just section. Don't rely on data-section attribute in your HTML - it's still not good if you have "section" as the duplicate html id's and as duplicate JSON keys.
If you have only one section id in HTML DOM, then in your JSON you must also have just one thing called "section" e.g.:
var whatever = {
"section" : {
"1": {
"question" : {
"1" : {
"id" : "1a",
"title" : "question1a"
},
"2" : {
"id" : "2a",
"title" : "question2a"
}
}
},
"2": {
"question" : {
"1" : {
"id" : "1a",
"title" : "aquestion1a"
},
"2" : {
"id" : "2a",
"title" : "aquestion2a"
}
}
}
}
}
console.log(whatever.section[1].question[1].title); //"question1a"
To get question, do something like this:
function loadQuestions(mySectionNum) {
$.getJSON('whatever.json', function(data){
var layeriwant = data.section[mySectionNum].question;
$.each(layeriwant, function(question, qMeta) {
var desired = '<div id="question-' +
qMeta.id +
'"' +
'>' +
'</div>';
$("#section").append(desired);
var quest = $("#question-" + qMeta.id);
quest.append('<div class="title">' + qMeta.title + '</div>');
//and so on for question content, answer choices, etc.
});
});
}
then something like this to actually get the questions:
function newQuestion(){
var myHTMLSecNum = $("#section").attr('data-section');
loadQuestions(myHTMLSecNum);
}
newQuestion();
//below is an example, to remove and then append new question:
$('#whatevernextbutton').on('click',function(){
var tmp = parseInt($("#section").attr('data-section'));
tmp++;
$("#section").attr('data-section', tmp);
$("#section").find('*').remove();
newQuestion();
});
Technically your getJSON function always retrieves the same data. Your code never compares the id given to the id you're extracting.
Your getJSON should look something like:
function loadQuestion( $section ) {
for (var i = 0; i < questions.section.length; i++) {
var item = questions.section[i];
if (item.id === $section) {
for (var j = 0; j < item.questions.length; j++) {
$('#questions').append('<li id="' +
item.questions[i].id + '">' +
item.questions[i].title +
' <button class="btn" data-response="a">A</button><button class="btn" data-response="b">B</button></li>'
);
}
}
}
}
Modify your JSON to:
var questions = {
section: [{
id: 1,
questions: [{
id: "1a",
title: "This is question1a"
},{
id: "2a",
title: "This is question2a"
}]},{
id: 2,
questions: [{
id: "1a",
title: "This is question1a"
},{
id: "2a"
title: "This is question2a"
}]
}]
};
Edit: your first parameter of getJSON is the URL of the JSON returning service.
You don't need getJSON at all if your JSON is already defined on the client. I have modified the code above.

How to select a row in Jquery datatable

I am using datatables in my application. Whenever user click on any row I want to highlight it and pick some values from selected row.
"oTableTools": {
"sRowSelect": "single",
"fnRowSelected": function ( node ) {
var s=$(node).children();
alert("Selected Row : " + $s[0]);
}
I tried sRowSelect and fnRowSelected but no luck. The row is not highlighted and neither fnRowSelected is called. Even no error on console.
Here is my complete code
var userTable = $('#users').dataTable({
"bPaginate": true,
"bScrollCollapse": true,
"iDisplayLength": 10,
"bFilter": false,
"bJQueryUI": true,
"sPaginationType": "full_numbers",
"oLanguage": {
"sLengthMenu": "Display _MENU_ records per page",
"sZeroRecords": "Enter a string and click on search",
"sInfo": "Showing _START_ to _END_ of _TOTAL_ results",
"sInfoEmpty": "Showing 0 to 0 of 0 results",
"sInfoFiltered": "(filtered from _MAX_ total results)"
},
"aaSorting": [[ 0, "asc" ]],
"aoColumns": [/* Name */ null,
/*Institution*/null,
/*Email*/null],
"oTableTools": {
"sRowSelect": "single",
"fnRowSelected": function ( node ) {
alert("Clicked");
}
}
});
Am I missing anything ?
EDIT:
Now able to highlight selected row.Added class="display" to HTML table. Still wondering why I didn't find this in datatable docs. Now looking how to collect selected values.
Here is how I do it
just add this function to your page (if users is your table id)
$("#users tbody").delegate("tr", "click", function() {
var iPos = userTable.fnGetPosition( this );
if(iPos!=null){
//couple of example on what can be done with the clicked row...
var aData = userTable.fnGetData( iPos );//get data of the clicked row
var iId = aData[1];//get column data of the row
userTable.fnDeleteRow(iPos);//delete row
}
When you are using fnRowSelected (i.e. when creating new tabletool) you have to use
"sRowSelect": "multi",
That will resolve the issue. Please increment my comment count if it helps. I need to have more points.
I used it in my code as follows
pqrtbl = new TableTools(NameOfTbl, { "sRowSelect": "multi",
"fnRowSelected": function ( node ) {
var s= $(node).children();
fnAddToSelLst(s[1].innerText);
},.......................
//column index depend upon your req.
The selected class should be, Within your function you used $s and you define var s which is not the same var.
"oTableTools": {
"sSelectedClass": "yourclassname",
"sRowSelect": "single",
"fnRowSelected": function ( node ) {
var s=$(node).children();
alert("Selected Row : " + s[0]);
}
}
If you wanna select multiple row, wanna get the data of selected row for ajax purpose check this
http://jsfiddle.net/ezospama/1/
DataTable code will be as follows
$(document).ready(function() {
var table = $('#datatable').DataTable();
$('#datatable tbody').on( 'click', 'tr', function (){
$(this).toggleClass('selected');
} );
$('#btn').click( function () {
console.log(table.rows('.selected').data());
alert("Check the console for selected data");
} );
})

Categories