jQuery DataTable Order Table Based On Checkbox - javascript

I have a table:
<table id="Equipment-Table" class="table table-bordered table-hover">
<thead>
<tr>
<th class="text-center">
#Html.DisplayNameFor(model => model.TypeOfEquipment)
</th>
<th class="text-center">
#Html.DisplayNameFor(model => model.Deleted)
</th>
<th></th>
</tr>
</thead>
<tbody>
#foreach (var item in Model)
{
<tr class="text-center">
<td>
#Html.DisplayFor(modelItem => item.TypeOfEquipment)
</td>
<td>
#Html.DisplayFor(modelItem => item.Deleted)
</td>
<td>
#Html.ActionLink("Edit", "Edit", new { id = item.Id }) |
#Html.ActionLink("Details", "Details", new { id = item.Id }) |
#Html.ActionLink("Delete", "Delete", new { id = item.Id })
</td>
</tr>
}
</tbody>
</table>
I am using jQuery DataTables to style it and give it functionality.
This produces this:
My goal:
Order by the Deleted column. I want deleted items to be at the bottom of the list.
Here is what I have so far:
$(document).ready(function() {
var equipmentTable = $("#Equipment-Table").DataTable({
"order": [1, "asc"],
"aoColumnDefs": [
{ "bSortable": false, "aTargets": [1, 2] },
{ "bSearchable": false, "aTargets": [1, 2] }
]
});
});
How can I make this happen?
Update
<tr class="text-center">
<td>
#Html.DisplayFor(modelItem => item.TypeOfEquipment)
</td>
#if (item.Deleted)
{
<td data-order="1">
#Html.DisplayFor(modelItem => item.Deleted)
</td>
}
else
{
<td data-order="0">
#Html.DisplayFor(modelItem => item.Deleted)
</td>
}
<td>
#Html.ActionLink("Edit", "Edit", new { id = item.Id }) |
#Html.ActionLink("Details", "Details", new { id = item.Id }) |
#Html.ActionLink("Delete", "Delete", new { id = item.Id })
</td>
</tr>
$(document).ready(function() {
var equipmentTable = $("#Equipment-Table").DataTable({
"aoColumnDefs": [
{ "bSortable": false, "aTargets": [1, 2] },
{ "bSearchable": false, "aTargets": [1, 2] }
]
});
$('#Equipment-Table input[type="checkbox"]').on('change', function () {
// Update data-sort on closest <td>
$(this).closest('td').attr('data-order', this.checked ? 1 : 0);
// Store row reference so we can reset its data
var $tr = $(this).closest('tr');
// Force resorting
equipmentTable
.row($tr)
.invalidate()
.order([1, 'asc'])
.draw();
});
});

You are using the legacy DataTables API: you should avoid using that, because it is being replaced by a more verbose and readable one.
You can sort your checkbox column programatically by using a combination of the following strategy:
When the page is first rendered, set the data-sort / data-order attribute to reflect the (un)checked status. In the example below, I settled for 0 for unchecked and 1 for checked. This should be handled by your templating/layout logic.
<!-- Rendered markup for UNCHECKED -->
<td data-order="0"><input type="checkbox" /></td>
<!-- Rendered markup for CHECKED -->
<td data-order="1"><input type="checkbox" checked /></td>
We bind a click event handler to the checkbox input. When the onChange event is fired, we simply:
Dynamically update the data-sort/data-order attribute based on the checked status of the checkbox
Invalidate the cached data stored for the row (so DataTables will have to reindex the data-sort/data-order attribute), using .row().invalidate()
Resort the table using .sort()
Trigger redrawing using .draw(), as the step above does not reflow/redraw the table
Here is a proof-of-concept example:
$(document).ready(function() {
var equipmentTable = $("#Equipment-Table").DataTable({
"order": [1, "asc"]
});
// Listen to change event from checkbox to trigger re-sorting
$('#Equipment-Table input[type="checkbox"]').on('change', function() {
// Update data-sort on closest <td>
$(this).closest('td').attr('data-order', this.checked ? 1 : 0);
// Store row reference so we can reset its data
var $tr = $(this).closest('tr');
// Force resorting
equipmentTable
.row($tr)
.invalidate()
.order([ 1, 'asc' ])
.draw();
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/datatables/1.10.16/js/jquery.dataTables.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/datatables/1.10.16/css/jquery.dataTables.min.css" rel="stylesheet" />
<table id="Equipment-Table" class="table table-bordered table-hover">
<thead>
<tr>
<th class="text-center">
Type of Eqiupment
</th>
<th class="text-center">
Deleted
</th>
<th></th>
</tr>
</thead>
<tbody>
<tr class="text-center">
<td>Lorem</td>
<td data-order="0"><input type="checkbox" /></td>
<td>...</td>
</tr>
<tr class="text-center">
<td>Ipsum</td>
<td data-order="0"><input type="checkbox" /></td>
<td>...</td>
</tr>
<tr class="text-center">
<td>Dolor</td>
<td data-order="1"><input type="checkbox" checked /></td>
<td>...</td>
</tr>
<tr class="text-center">
<td>Sit</td>
<td data-order="1"><input type="checkbox" checked /></td>
<td>...</td>
</tr>
<tr class="text-center">
<td>Amet</td>
<td data-order="0"><input type="checkbox" /></td>
<td>...</td>
</tr>
</tbody>
</table>
Update
It seems like OP is only interested in enforcing initial sorting of the table, while disabling user-initiated sorting and search. The checkboxes are also disabled by default, which means we do not need to bind event listeners to them since we do not expect the user to toggle this option. This can be done with the following config:
{
"order": [1, "asc"],
"columnDefs": [
{ "orderable": false, "targets": [0,1,2] },
],
"searching": false
}
Proof-of-concept:
$(document).ready(function() {
var equipmentTable = $("#Equipment-Table").DataTable({
"order": [1, "asc"],
"columnDefs": [{
"orderable": false,
"targets": [0, 1, 2]
}],
"searching": false
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/datatables/1.10.16/js/jquery.dataTables.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/datatables/1.10.16/css/jquery.dataTables.min.css" rel="stylesheet" />
<table id="Equipment-Table" class="table table-bordered table-hover">
<thead>
<tr>
<th class="text-center">
Type of Eqiupment
</th>
<th class="text-center">
Deleted
</th>
<th></th>
</tr>
</thead>
<tbody>
<tr class="text-center">
<td>Lorem</td>
<td data-order="0"><input type="checkbox" disabled /></td>
<td>...</td>
</tr>
<tr class="text-center">
<td>Ipsum</td>
<td data-order="0"><input type="checkbox" disabled /></td>
<td>...</td>
</tr>
<tr class="text-center">
<td>Dolor</td>
<td data-order="1"><input type="checkbox" checked disabled /></td>
<td>...</td>
</tr>
<tr class="text-center">
<td>Sit</td>
<td data-order="1"><input type="checkbox" checked disabled /></td>
<td>...</td>
</tr>
<tr class="text-center">
<td>Amet</td>
<td data-order="0"><input type="checkbox" disabled /></td>
<td>...</td>
</tr>
</tbody>
</table>

Related

Compare two cells in a html table and highlight row if different

I have an HTML table (tree table precisely but it doesn't matter) and it has several columns. For each row, it is very important that the values in one of the columns should be higher than the other column. If that is not the case then I'd like to highlight that entire row. How do I do that?
My HTML code looks like this:
<table id="stepstats-list-exp">
<thead>
<tr>
<th> name </th>
<th> elp_01 </th>
<th> elp_20 </th>
<th> scal </th>
</tr>
</thead>
<tbody>
<tr data-tt-id=864845 data-tt-parent-id=>
<td> 'Init' </td>
<td class="elp_01"> 0 </td>
<td class="elp_20"> 0 </td>
<td class="scal"> 0.00 </td>
</tr>
<tr data-tt-id=864846 data-tt-parent-id=864845>
<td> 'Update' </td>
<td class="elp_01"> 0 </td>
<td class="elp_20"> 0 </td>
<td class="scal"> 0.00 </td>
</tr>
<tr data-tt-id=864847 data-tt-parent-id=>
<td> 'Load' </td>
<td class="elp_01"> 32 </td>
<td class="elp_20"> 31 </td>
<td class="scal"> 1.03 </td>
</tr>
</tbody>
</table>
In all my test cases, elp_20 should always be smaller than elp_01. If not, the entire row needs to be highlighted. For that purpose, I have this jQuery code that doesn't seem to be working. For each tr row, I'm checking each td column and comparing values.
<script type="text/javascript">
/* Highlight row if elp_20 > elp_01 */
$(document).ready(function () {
$("#stepstats-list-exp tr").each(function () {
$(this).find('td').each(function(){
if (parseInt($(".elp_20").text(), 10) < parseInt($(".elp_01").text(), 10)) {
$(this).parent("tr").css('background-color', 'crimson');
$(this).parent("tr").css('font-weight','bold');
$(this).parent("tr").css('color','white');
}
});
});
});
</script>
This working snippet accesses the table rows as an html collection that can be looped through to compare the values represented by the contents of the second and third cell of each row. An inline style attribute it used to highlight the row (alternative styling could be made by adding or toggling class names if something more complex is needed)
let tableRows = document.getElementById("stepstats-list-exp").getElementsByTagName('tr');
for (let i=0; i<tableRows.length; i++)
if (Number(tableRows[i].children[2].innerText) >= Number(tableRows[i].children[1].innerText)) {
tableRows[i].setAttribute("style", "background: yellow");
}
<table id="stepstats-list-exp">
<thead>
<tr>
<th> name </th>
<th> elp_01 </th>
<th> elp_20 </th>
<th> scal </th>
</tr>
</thead>
<tbody>
<tr data-tt-id=864845 data-tt-parent-id=>
<td> 'Init' </td>
<td class="elp_01"> 0 </td>
<td class="elp_20"> 0 </td>
<td class="scal"> 0.00 </td>
</tr>
<tr data-tt-id=864846 data-tt-parent-id=864845>
<td> 'Update' </td>
<td class="elp_01"> 0 </td>
<td class="elp_20"> 0 </td>
<td class="scal"> 0.00 </td>
</tr>
<tr data-tt-id=864847 data-tt-parent-id=>
<td> 'Load' </td>
<td class="elp_01"> 32 </td>
<td class="elp_20"> 31 </td>
<td class="scal"> 1.03 </td>
</tr>
</tbody>
</table>
You can just iterate through the classes, add them to a variable and iterate with a for loop, if you need to iterate one elp_01 to all elp_20 just map it.
Here's an example:
let firstColumn = document.getElementsByClassName('elp_01').innerText
let secondColumn = document.getElementsByClassName('elp_20').innerText
for (let i = 0; i < firstColumn.length; i ++) {
if (firstColumn[i] > secondColumn[i]) {
// Something - maybe add a class in css to color the row and add it to the element
}
else {
// Something else
}
}

Checkboxes in DataTables need to capture all checked values

I am having 100s of items in my datatable, displayed using 'forEach' in script as below
<div class="panel-body">
<table class="table table-striped" id="table1">
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">Name</th>
<th scope="col">Customer</th>
<th scope="col">CheckBoxes</th>
</tr>
</thead>
<tbody>
<c:forEach items="${list}" varStatus="status" var="name">
<tr>
<td>${status.index + 1}</td>
<td>${name.getName()}</td>
<td>${name.getCustomer()}</td>
<td>
<input type="checkbox" class="custom-control-input" id="checkRule" value="${rule.getName()}">
</td>
</tr>
</c:forEach>
</tbody>
</table>
</div>
What I am trying is, upon checking respective checkboxes, I need those value to be fetched and sent in AJAX (POST).
$(document).ready(function(){
const myArray = [];
$('#checkRule').click(function(){
console.log('checked');
if( $('#checkRule').is(':checked') ) {
myArray.push( $('#checkRule').val() );
console.log(myArray);
}else{
const index = myArray.indexOf( $('#checkRule').val() );
if (index > -1) {
myArray.splice(index, 1);
}
console.log(myArray);
}
});
$('#correlation_table').DataTable();
$('#send').click(function(){
var result = myArray;
console.dir('Import result >>>>> ',result);
$.ajax({
url: "sendAll",
headers: {
'Accept': 'text/plain',
'Content-Type': 'application/json'
},
type: "POST",
dataType: "html",
data: JSON.stringify(result),
success :function(data) {
console.log(data);
},
error :function(err){
console.log(err);
}
});
});
});
Upon using this above code, I am reaching nowhere.
Console output for "console.log('Import result >>>>> ',result);" is
Import result >>>>> Array []
How can I get all 'Name' upon checking multiple checkboxes in table?
You have given same ids to all your checkboxes so only first checkboxes value you will be getting in your array instead use class selector instead of id and then simply use $(this) to get the reference of checkbox change and add those values in your array using .val()
Demo Code :
$(document).ready(function() {
const myArray = [];
//use class here
$('.checkRule').change(function() {
//use `this` to get refernce of current checkbox change
if ($(this).is(':checked')) {
myArray.push($(this).val()); //put that value
} else {
const index = myArray.indexOf($(this).val());
if (index > -1) {
myArray.splice(index, 1);
}
}
});
$('#correlation_table').DataTable();
$('#send').click(function() {
var result = myArray;
console.log('Import result >>>>> ', result);
//your ajax call..
});
});
<div class="panel-body">
<link rel='stylesheet' type='text/css' href='https://cdn.datatables.net/1.10.22/css/jquery.dataTables.min.css'>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdn.datatables.net/1.10.22/js/jquery.dataTables.min.js"></script>
<table class="table table-striped" id="correlation_table">
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">Name</th>
<th scope="col">Customer</th>
<th scope="col">CheckBoxes</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>sss</td>
<td>123</td>
<td>
<!-- use class instead of id-->
<input type="checkbox" class="custom-control-input checkRule" value="ss">
</td>
</tr>
<tr>
<td>2</td>
<td>ses</td>
<td>23</td>
<td>
<input type="checkbox" class="custom-control-input checkRule" value="ses">
</td>
</tr>
<tr>
<td>3</td>
<td>sswi</td>
<td>13</td>
<td>
<input type="checkbox" class="custom-control-input checkRule" value="sswi">
</td>
</tr>
<tr>
<td>4</td>
<td>ssww</td>
<td>12</td>
<td>
<input type="checkbox" class="custom-control-input checkRule" value="ssww">
</td>
</tr>
</tbody>
</table>
</div>
<button id="send">SEnd</button>

Adding the sum of a field in Datatables

This question has been asked before but as an absolute beginner with JavaScript I don't know how to apply this to my code. I would like the sum for both the 'G' field and sum for the 'AB' field to be displayed in the footer of my table.
Here's my code
<div align="center">
<table id = 'battingtbl' class="display compact nowrap">
<thead>
<tr>
<th>YEAR</th>
<th>AGE</th>
<th>G</th>
<th>AB</th>
</tr>
</thead>
<tbody>
{% for stat in playerdata.masterbatting_set.all %}
<tr>
<td>{{ stat.year }}</td>
<td>{{ stat.age }}</td>
<td>{{ stat.g }}</td>
<td>{{ stat.ab }}</td>
</tr>
{% endfor %}
</tbody>
</table>
<script>
$(document).ready(function () {
$('#battingtbl').DataTable({
"searching": true,
"pageLength": 40,
"scrollX": true,
"paging": false,
"info": false,
})
});
</script>
I normally do not suggest to populate DataTable with HTML source, I find this way tedious and slow.
However, assuming you want those totals to get recalculated upon each re-draw (table filtering), I'd suggest to employ drawCallback option to populate your totals:
drawCallback: () => {
// grab DataTables insurance into the variable
const table = $('#battingtbl').DataTable();
// extract all the data for all visible columns
const tableData = table.rows({search:'applied'}).data().toArray();
// summarize row data for columns 3,4 (indexes 2, 3)
const totals = tableData.reduce((total, rowData) => {
total[0] += parseFloat(rowData[2]);
total[1] += parseFloat(rowData[3]);
return total;
// starting point for reduce() totals for 2 columns equal to zero each
}, [0,0]);
// populate footer cells for columns 3, 4 (indexes 2, 3) with corresponding array total
$(table.column(2).footer()).text(totals[0]);
$(table.column(3).footer()).text(totals[1]);
}
Above requires you to append <tfoot> section to the static HTML part you prepare server-side:
<tfoot>
<tr>
<th colspan="2">Totals:</th>
<th></th>
<th></th>
</tr>
</tfoot>
So, complete example might look something, like this:
<!doctype html>
<html>
<head>
<script type="application/javascript" src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<script type="application/javascript" src="https://cdn.datatables.net/1.10.19/js/jquery.dataTables.min.js"></script>
<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/1.10.19/css/jquery.dataTables.min.css">
</head>
<body>
<div align="center">
<table id = 'battingtbl' class="display compact nowrap">
<thead>
<tr>
<th>YEAR</th>
<th>AGE</th>
<th>G</th>
<th>AB</th>
</tr>
</thead>
<tbody>
<tr>
<td>2016</td>
<td>24</td>
<td>15</td>
<td>6</td>
</tr>
<tr>
<td>2018</td>
<td>32</td>
<td>5</td>
<td>7</td>
</tr>
<tr>
<td>2016</td>
<td>28</td>
<td>14</td>
<td>9</td>
</tr>
<tr>
<td>2015</td>
<td>25</td>
<td>9</td>
<td>7</td>
</tr>
</tbody>
<tfoot>
<tr>
<th colspan="2">Totals:</th>
<th></th>
<th></th>
</tr>
</tfoot>
</table>
<script>
$(document).ready(function () {
$('#battingtbl').DataTable({
"searching": true,
"pageLength": 40,
"scrollX": true,
"paging": false,
"info": false,
drawCallback: () => {
const table = $('#battingtbl').DataTable();
const tableData = table.rows({
search: 'applied'
}).data().toArray();
const totals = tableData.reduce((total, rowData) => {
total[0] += parseFloat(rowData[2]);
total[1] += parseFloat(rowData[3]);
return total;
}, [0, 0]);
$(table.column(2).footer()).text(totals[0]);
$(table.column(3).footer()).text(totals[1]);
}
})
});
</script>
</body>
</html>

Adding static header name while making dynamic table

I am making a table which row & column depend on JSON
JSON:
$scope.dataToShow=[
tableHeder=["First Name","Age"],
{
name:"rahim",
age:23
},
{
name:"karim",
age:24
}
];
My code:
<table>
<tr>
<th>Select</th>
<th ng-repeat="header in dataToShow.tableHeader"></th>
</tr>
<tr ng-repeat="row in dataToShow">
<td>
<input type="checkbox">
</td>
<td ng-repeat="item in row">{{item}}</td>
</tr>
</table>
I want my view like:
Select Name age
checkbox rahim 23
checkbox karim 24
But my I am getting:
Select
Checkbox Name age
Checkbox rahim 23
Checkbox karim 24
How can I solve it???
if the JSON response is not from backend, do some modifications
JSON:
$scope.dataToShow={
tableHeder:["First Name","Age"],
tableData: [{
name:"rahim",
age:23
},
{
name:"karim",
age:24
}]
};
HTML:
<table>
<tr>
<th>Select</th>
<th ng-repeat="header in dataToShow.tableHeader">{{header}}</th>
</tr>
<tr ng-repeat="row in dataToShow.tableData">
<td>
<input type="checkbox">
</td>
<td >{{row.name}}</td>
<td >{{row.age}}</td>
</tr>
</table>
This will definitely work
Try this code :
<table>
<tr>
<th>Select</th>
<th>{{dataToShow.tableHeder[0]}}</th>
<th>{{dataToShow.tableHeder[1]}}</th>
</tr>
<tr ng-repeat="row in dataToShow">
<td>
<input type="checkbox">
</td>
<td >{{row.name}}</td>
<td >{{row.age}}</td>
</tr>
</table>
Using $index you can get the index number of the loop.

how can i place a specific row(based on column value) always at bottom of table with ng-table?

I am new to AngularJs and ng-table, I tried to sort the ng-table with the sortable attribute its working fine but I had a row with the final result, here how can I use sortable with out impact on a specific row?
<table ng-table="tableParams" ng-model="Controller.data" class="table" show-filter="true">
<tr ng-if="entry.task_name!='Totals'" ng-class="{info: $even, active: $odd}" ng-repeat="entry in $data">
<td data-title="'Task Name'" sortable="'taskName'" filter="{ 'taskName': 'text' }"><div ng-show="entry.taskName!=false">{{entry.taskName}}</div></td>
<td data-title="'Planned Hours'" sortable="'plannedHours'">{{entry.plannedHours}}</td>
<td></td>
</tr>
<tr ng-if="entry.task_name ==='Totals'" ng-class="{info: $even, active: $odd}" ng-repeat="entry in $data">
<td data-title="'Task Name'" >{{entry.taskName}}</td>
<td data-title="'Planned Hours'">{{entry.plannedHours}}</td>
<td></td>
</tr>
<tr>
<td ng-show="repCtrl.noData" ng-bind="repCtrl.noData"></td>
</tr>
</table>
did you try to put this row in <tfoot>?
<table ng-table="tableParams" ng-model="Controller.data" class="table" show-filter="true">
<tbody>
<tr ng-class="{info: $even, active: $odd}" ng-repeat="entry in $data | filter: myFilter">
<td data-title="'Task Name'" sortable="'taskName'" filter="{ 'taskName': 'text' }">
<div ng-show="entry.taskName!=false">{{entry.taskName}}</div>
</td>
<td data-title="'Planned Hours'" sortable="'plannedHours'">{{entry.plannedHours}}</td>
<td></td>
</tr>
<tr>
<td ng-show="repCtrl.noData" ng-bind="repCtrl.noData"></td>
</tr>
</tbody>
<tfoot>
<tr ng-repeat="entry in $data | filter: {taskName:'Totals'}">
<td>{{entry.taskName}}</td>
<td>{{entry.plannedHours}}</td>
<td></td>
</tr>
</tfoot>
</table>
<script>
$scope.myFilter = function (item) {
return item.taskName !== 'Totals';
};
</script>
my plnkr with different data, but working as you expected: http://plnkr.co/edit/Rx7Kqp?p=preview

Categories

Resources