Nested DataTable editable with Ajax Source Data
Nested DataTable editable with Ajax Source Data
I have one or two questions about the following code snippet. I want to populate parentData and childData with a sql query. I have a php file with the query and json_encode of the result. How can I pass this query to the used variable in the js? My 2nd question: I want the individual lines of the childData to be editable and to be updated in the database. For this, the data of the corresponding line should be transferred to a modal. Whats the best way to do this? I found a similar example for my desired result: example here
I'm interested: is it possible with the help of the editor to make SQL queries from the table also with Group_Concat or are there only left joins? If so, how can I solve the problem and pass the data? So far I have the problem that I do not get the td.details-control integrated. Therefore, the sample code is hardcoded data. So my goal is an editable DataTable with 2 separate SQL statements for the parent and child tables.
Thanks in advance.
HTML-Code
<!DOCTYPE html>
<html>
<head>
<script src="http://code.jquery.com/jquery-1.11.3.min.js"></script>
<link href="https://nightly.datatables.net/css/jquery.dataTables.css" rel="stylesheet" type="text/css" />
<script src="https://nightly.datatables.net/js/jquery.dataTables.js"></script>
<meta charset=utf-8 />
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<link href="https://netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://cdn.datatables.net/1.10.19/js/jquery.dataTables.min.js"></script>
<link href="https://cdn.datatables.net/1.10.19/css/jquery.dataTables.min.css" rel="stylesheet"/>
<title>DataTables - JS Bin</title>
</head>
<body>
<div class="panel panel-default">
<div class="panel-heading"><h3>Overview</h3></div>
<div class="panel-body">
<table id="mytable" class="table table-condensed table-hover" width=100%">
</table>
</div>
</div>
<div class="modal fade" id="editModal" role="dialog">
<div class="modal-dialog">
<div id="content-data"></div>
</div>
</div>
</body>
</html>
JS
const parentData = [
{column1: 's01', column2: '200 250', column3: 'A / B / C'},
{column1: 's02', column2: '100 200', column3: 'A / D'},
{column1: 's03', column2: '100 300', column3: 'E / F'}
];
const childData = {
s01: [
{column1: 'p1', column2: '5', column3: 'yes', column4: '100 200', column5: 's02', column6: '1', tagged: '0'},
{column1: 'p2', column2: '4', column3: 'yes', column4: '150 250', column5: 's06', column6: '3', tagged: '0'},
{column1: 'p3', column2: '1', column3: 'yes', column4: '150 250', column5: 's07', column6: '71', tagged: '1'},
{column1: 'p4', column2: '2', column3: 'yes', column4: '100', column5: 's03', column6: '35', tagged: '1'}
],
s02: [
{column1: 'p1', column2: '1', column3: 'yes', column4: '150 200', column5: 's02', column6: '21', tagged: '1'},
{column1: 'p2', column2: '3', column3: 'no', column4: '200 250', column5: 's03', column6: '32', tagged: '1'}
],
s03: [
{column1: 'p1', column2: '3', column3: 'yes', column4: '100', column5: 's03', column6: '31', tagged: '1'},
{column1: 'p2', column2: '2', column3: 'yes', column4: '150 300', column5: 's06', column6: '62', tagged: '1'},
{column1: 'p3', column2: '1', column3: 'no', column4: '150', column5: 's01', column6: '13', tagged: '1'}
]
};
const dataTable = $('#mytable').DataTable({
"paging": false,
"lengthChange": false,
"info": false,
data: parentData,
columns: [
{
"className": 'details-control',
"orderable": false,
"data": null,
"defaultContent": ''
},
{title: 'Col 1', data: 'column1'},
{title: 'Col 2', data: 'column2'},
{title: 'Col 3', data: 'column3'}
],
"order": [[1, 'asc']]
});
$('#mytable').on('click', 'td.details-control', function(){
const parentRow = dataTable.row($(this).closest('tr'));
parentRow.child.isShown() ?
parentRow.child.remove() :
parentRow.child('<table id="details'+parentRow.data().column1+'" class="table table-condensed table-hover"></table>').show();
$(this).closest('tr').toggleClass('shown');
if(!parentRow.child.isShown()) return;
const detailsData = childData[parentRow.data().column1];
$('#details'+parentRow.data().column1).DataTable({
sDom: 't',
data: detailsData,
columns: [
{title: 'Child 1', data: 'column1'},
{title: 'Child 2', data: 'column2'},
{title: 'Child 3', data: 'column3'},
{title: 'Child 4', data: 'column4'},
{title: 'Child 5', data: 'column5'},
{title: 'Child 6', data: 'column6'},
{title: 'Tagged', data: 'tagged', "render": function (data, type, row) {
return (data === '1') ? '<span class="glyphicon glyphicon-ok"></span>' : '<span class="glyphicon glyphicon-remove"></span>';}
},
{title: 'Action', "render": function (data, type, row) {
return '<button type="button" class="btn btn-primary btn-xs" data-toggle="modal" data-target="#editModal" data-id="1"><i class="glyphicon glyphicon-pencil"> </i>Edit</button>';}
}
]
});
});
This question has accepted answers - jump to:
Answers
"So my goal is an editable DataTable with 2 separate SQL statements for the parent and child tables."
The best for this is to use Editor. I have been using this on many occasions. Here is a blog on this:
https://datatables.net/blog/2016-03-25
If you need to "prepare" the data you read (e.g. using GROUP_CONCAT and the likes) to be processed with Editor I recommend you use views. That works very well and makes your Editor code less complex too.
You can also use proprietary getFormatters with Editor that allow you to retrieve just about anything for each individual Editor column. Same applies to the use of setFormatters in case you need more flexibility.
https://editor.datatables.net/manual/php/formatters
Thanks for the helpful links, I've come a bit ahead (I think so) but do you have an example for building a view with the editor? I would like to represent the following SQL statement:
I've filled my table with a sample query and at least I've been able to integrate the query and td.details-control, which I had problems with before. Looks like this now
This is the editor example query for the picture shown
Child table is still unfilled. How do I pass (in my example the host name) to the SQL query for the child table to be created? Would be great if you could help me there
Hi, you can't CREATE a view with Editor but you can USE it in Editor:
Here is how to create a view in MySQL (should also work with other relational DBMSs):
Subsequently you can query this view with SQL but also with Editor:
SQL:
would return your columns Hostname, VLAN and Location.
Not sure why you wrote 'Hostname' instead of Hostname. Never seen that with quotation marks before. It is a variable name and not a string actually.
This is how you can create any kind of view in MySQLWorkbench which I would recommend as a tool:
Let me give you a simple example from my own coding. It is actually the simplest I could find but should have all that you need. I have filters and those filters that the user can freely define have value ranges.
Data Model:
This part of the code ties the two tables together. Filtr as parent and valueRange as child:
And the JS code (deleted all the Data tables and editor events to make it shorter):
And the PHP:
First of all thank you. That was a good help for me.
"Not sure why you wrote 'Hostname' instead of Hostname. Never seen that with quotation marks before. It is a variable name and not a string actually."
I think the column names were strings before, of course it makes no sense in this case, you're right.
Have now got the parent and child table filled over the view. However, the where clause for the child table does not work yet. Get the error message that .row() would be no function or the problem that no data is loaded at all. I have to take a closer look at this tomorrow, so far all the child tables are filled with the same content.
How can I get the id or hostname of the table row? The query for the child table works so far, if I mark the row before I click on td.details-control. But I want the id / hostname to be passed by td.details-control without first marking the row. I tried to get the Id in the onclick event via "table.row(tr).data()", but that didn't work.
GoT it, the question is obsolet. I couldn‘t delete the post anymore