Apply a custom filter to an open child table
Apply a custom filter to an open child table
Link to test case:
I use internal data to fill the table so I am not allowed to share a case.
Error messages shown:
tests_table.draw() is not a function
Description of problem:
Hi, I use child tables to show detailed informations of the respective parent row. I use two checkboxes to filter the parent table rows and it is working perfect. I do that by applying an attribute to every row depending on data I get.
I want to apply the same thing to the opened child table (I know that i cannot search/filter child tables when they are not open), but I always get the error, that I cannot draw the child table.
Screenshot of the Website for better understanding
The parent table ist filtered and in the state in which the site on the picture is I want the second row of the child table also not visible/filtered.
This is the code used to build the tables.
var build_table = $('#build_table').DataTable({
"ajax":{
"type": "post",
"data": {'post_release': release_value, 'post_responsible': responsible_value},
"url":"get_init.php", //Alternative get.php
"dataSrc" : ""
},
paging: false,
autoWidth: true,
columns: [{
className: 'term-details-control',
orderable: false,
data: null,
defaultContent: '<img src="https://pics.freeicons.io/uploads/icons/png/9322424801588529853-24.png">'
},
{ data: "WDM_GMRE" },
{ data: "OCS_GMRE" },
{ data: "PSIM_GMRE" },
{ data: "WDM_NE" },
{ data: "OCS_NE" },
{ data: "PSIM_NE" },
{ data: "tests_total" ,
render: function ( data, type, row ) {
if (row.tests_failed > 2) {
return '<span class="dot" style="height: 20px; width: 20px; background-color: red; border-radius: 25%; display: inline-block;"></span> ' + data + " / " + row.tests_passed + " / " + row.tests_failed;
} else {
return '<span class="dot" style="height: 20px; width: 20px; background-color: green; border-radius: 25%; display: inline-block;"></span> ' + data + " / " + row.tests_passed + " / " + row.tests_failed;
}
}
},
{ data: "WDM_tests" ,
render: function ( data, type, row) {
return data;
}
},
{ data: "MRN_tests" ,
render: function ( data, type, row) {
return data;
}
},
{ data: "green_succ",
render: function ( data, type, row ) {
return data + '% successfull'
}
},
{ data: "ess_succ",
render: function ( data, type, row ) {
return '<progress value="' + data + '" max="100"></progress>'
}
}
],
"columnDefs": [
{ "searchable": true, "targets": 1 }
],
rowId: 'PK_comb_ID',
createdRow: function (tr, data) {
if ( data.b_SIM && data.b_HW == 1 ) {
$(tr).attr('banned', '0');
} else if (data.b_SIM == 1) {
$(tr).attr('banned', '1');
} else {
$(tr).attr('banned', '2')
}
},
order: [
[1, 'desc']
]
});
//Filter parent table
$('.filter_type').on('change', function() {
$.fn.dataTable.ext.search.push(
function(settings, data, dataIndex) {
if ($('#check4').prop('checked') && $('#check5').prop('checked')) {
return $(build_table.row(dataIndex).node()).attr('banned');
} else if ($('#check4').prop('checked')) {
return $(build_table.row(dataIndex).node()).attr('banned') == 0 || $(build_table.row(dataIndex).node()).attr('banned') == 2;
} else if ($('#check5').prop('checked')) {
return $(build_table.row(dataIndex).node()).attr('banned') == 0 || $(build_table.row(dataIndex).node()).attr('banned') == 1;
}
}
);
build_table.draw();
$.fn.dataTable.ext.search.pop();
})
// Add event listener for opening and closing details
$('#build_table tbody').on('click', 'td.term-details-control', function() {
var tr = $(this).closest('tr');
var row = build_table.row(tr);
if (row.child.isShown()) {
// This row is already open - close it
row.child.hide();
tr.removeClass('shown');
$('.odd img, .even img').attr('src', 'https://pics.freeicons.io/uploads/icons/png/9322424801588529853-24.png');
} else {
// Open this row
var te = $(this).closest('tr').attr('id');
row.child(formatTerm(te)).show();
tr.addClass('shown');
$('.odd.shown img, .even.shown img').attr('src', 'https://pics.freeicons.io/uploads/icons/png/6275201171582779176-20.png');
var tests_table = $('#tests_table' + te).dataTable({
dom: 'Qfrtip',
"ajax":{
"type": "post",
"data": {'post_release': release_value, 'post_id': te},
"url":"get.php",
"dataSrc" : ""
},
paging: false,
searching: true,
columns: [{
orderable: true,
defaultContent: ''
},
{ data: "test_name" ,
render: function ( data, type, row) {
return '<a target="_blank" href="' + row.test_url + '">' + data + '</a>';
}
},
{ data: "CSL" },
{ data: "tests_total" },
{ data: "tests_passed" },
{ data: "tests_failed" },
{ data: "Test_Datetime" }
],
createdRow: function (tr, data) {
if ( data.b_Green == 1 ) {
$(tr).addClass('green');
}
},
createdRow: function (tr, data) {
if ( data.b_SIM == 1 ) {
$(tr).attr('banned_', '1');
} else {
$(tr).attr('banned_', '0');
}
},
order: [
[6, 'desc']
]
})
});
counter += 1;
//Try to filter the child table(s) but with this getting the error "tests_table.draw(); not a function"
$('.filter_type').on('change', function() {
$.fn.dataTable.ext.search.push(
function(settings, data2, dataIndex) {
if ($('#check4').prop('checked') && $('#check5').prop('checked')) {
return $(tests_table.row(dataIndex).node()).attr('banned_');
} else if ($('#check4').prop('checked')) {
return $(tests_table.row(dataIndex).node()).attr('banned_') == 0;
} else if ($('#check5').prop('checked')) {
return $(tests_table.row(dataIndex).node()).attr('banned_') == 1;
}
}
);
tests_table.draw();
$.fn.dataTable.ext.search.pop();
}
});
}
function formatTerm(table_id) {
return '<table class="child_table" id="tests_table' + table_id + '">' +
'<thead><tr><th></th><th>Test Name</th><th>Responsible</th><th>Tests Total</th><th>Tests Passed</th><th>Tests Failed</th><th>Datetime</th></tr></thead></table>';
}
If this way of filtering is possible in any way, I am looking forward to any help.
This question has an accepted answers - jump to answer
Answers
We're happy to take a look, but as per the forum rules, please link to a test case - a test case that replicates the issue will ensure you'll get a quick and accurate response. Information on how to create a test case (if you aren't able to link to the page you are working on) is available here.
Cheers,
Colin
Looks like a scoping problem. You are creating the Datatable API on line 107, inside thee click event function. But you are trying to access the variable
tests_table
outside the function.You could make
tests_table
a global variable but if you have two child tables open then it might be confusing which table will be filtered. The last opened child will be assigned to the variable and that is the one that will be filtered.Kevin
No sorry that is not the case.
In the code example I posted it is the case but only because I made a mistake while cleaning up my code before posting it here. Sorry for that.
I double and triple checked it in the code I use and there it works.
You have
$('#tests_table' + te).dataTable(
in line 107. It should be$('#tests_table' + te).DataTable(
to get an instance of the API. Notice the capital 'D'. See this FAQ.Kevin
Wow...
Huge thanks for the help.
I am new to Datatables, as you may have noticed, but I did not know at all that this small "detail" would make a difference.