Color a Collapsible(Not Visible Data Column) Row
Color a Collapsible(Not Visible Data Column) Row
Hello,
I changed from a tabbed data table to a table that has collapsible rows grouped by Department and then by User.Title (Name). Here is what it looks like:
For each department, their are a certain number of employees. For IT, the only people in the Department are Name #1 and Name #2, so I want to $(row).addClass('green');
. If I want to do for each Department, based on the different values, how can I do that? Multiple AJAX calls?
Right now it is coloring the child row under Name #1 and Name # 2, instead of the collapsible row?
Here is my JS:
$.ajax({
url: uri,
method: "GET",
headers: {
"Accept": "application/json; odata=verbose"
},
success: function(data) { // success function which will then execute "GETTING" the data to post it to a object array (data.value)
console.log(data);
if (data.d != null && data.d != undefined && data.d.results.length > 0) {
var table = $('#myTable').DataTable();
table.rows.add(data.d.results).draw();
}
}
});
}
$(document).ready(function() {
var collapsedGroups = {};
var top = '';
var parent = '';
var table = $('#myTable').DataTable({
"pageLength" : 10,
"createdRow": function( row, data, dataIndex ) {
if ( data.MondayStatus == "P" && data.TuesdayStatus == "P" && data.WednesdayStatus == "P" && data.ThursdayStatus == "P" && data.FridayStatus == "P") {
$(row).addClass('green');
}
},
"columns": [
{"data": "Department",
visible: false},
{ "data": "User.Title",
visible: false },
{ "data": "Locations"},
{ "data": "Sunday",
render: function(data, type, row){
if(type === "sort" || type === "type"){
return data;
}
return moment(data).format("MM/DD/YYYY");
}
},
{ "data": "Monday",
render: function(data, type, row){
if(type === "sort" || type === "type"){
return data;
}
return moment(data).format("MM/DD/YYYY");
}
},
{"data": "MondayStatus",
visible: false},
{ "data": "Tuesday",
render: function(data, type, row){
if(type === "sort" || type === "type"){
return data;
}
return moment(data).format("MM/DD/YYYY");
}
},
{"data": "TuesdayStatus",
visible: false},
{ "data": "Wednesday",
render: function(data, type, row){
if(type === "sort" || type === "type"){
return data;
}
return moment(data).format("MM/DD/YYYY");
}
},
{"data": "WednesdayStatus",
visible: false},
{ "data": "Thursday",
render: function(data, type, row){
if(type === "sort" || type === "type"){
return data;
}
return moment(data).format("MM/DD/YYYY");
}
},
{"data": "ThursdayStatus",
visible: false},
{ "data": "Friday",
render: function(data, type, row){
if(type === "sort" || type === "type"){
return data;
}
return moment(data).format("MM/DD/YYYY");
}
},
{"data": "FridayStatus",
visible: false}
],
dom: "<'row'<'col-sm-12 col-md-10'f><'col-sm-12 col-md-2'B>>" +
"<'row'<'col-sm-12'tr>>" +
"<'row'<'col-sm-12 col-md-5'i><'col-sm-12 col-md-7'p>>",
buttons: [{
extend: 'collection',
className: "btn-dark",
text: 'Export/Update Table',
buttons: [{
extend: "excel",
className: "btn-dark"
},
{
extend: "print",
className: "btn-dark"
},
{
text: 'User Guide',
action: function (e, dt, node, config){
$('#ugModal').modal('show');
}
},
],
}],
order: [
[0, 'asc'],
[1, 'asc']
],
rowGroup: {
dataSrc: [
'Department',
'User.Title'
],
startRender: function(rows, group, level) {
var all;
if (level === 0) {
top = group;
all = group;
} else if (level === 1) {
parent = top + group;
all = parent;
// if parent collapsed, nothing to do
if (!collapsedGroups[top]) {
return;
}
} else {
// if parent collapsed, nothing to do
if (!collapsedGroups[parent]) {
return;
}
all = top + parent + group;
}
var collapsed = !collapsedGroups[all];
console.log('collapsed:', collapsed);
rows.nodes().each(function(r) {
r.style.display = collapsed ? 'none' : '';
});
//Add category name to the <tr>.
return $('<tr/>')
.append('<td colspan="8">' + group + ' (' + rows.count() + ')</td>')
.attr('data-name', all)
.toggleClass('collapsed', collapsed);
}
}
});
loadData();
$('#myTable tbody').on('click', 'tr.dtrg-start', function() {
var name = $(this).data('name');
collapsedGroups[name] = !collapsedGroups[name];
table.draw(false);
});
});
Answers
If you want to style the
tr
displayed by rowGroup then you would do this in therowGroupp.startRender
function. You can use thegroup
parameter or you may need to use a combination ofgroup
andlevel
depending on what you want to want style.Guessing you are saying that the
createdRow
function is setting the color which affects the table rows. thetr
returned in line 153 is where you would change the style of the rowGrouptr
.Kevin
@kthorngren so I added it under the startRender function after it returns
</tr>
, and it is still targeting the very child row under name and under department.The problem with that is the function has already returned so that statement is not executed. The addClass needs to be chained with the other methods in the return statement. Lots of ways you could do this but one option is to do something like this:
It may need some adjustment to work correctly. Like
data.TuesdayStatus
won't work because you are trying to access the table row data. Take a look at the docs forrowGroup.startRender
to see what all the parameters are. You can loop all therows
in the group to determine if the class needs added. Or you can use thegroup
name or you can use thelevel
value.Kevin
I understand how the data values will not work in this conditional, what if I created
Not sure how to call the rows/groups/levels like that
As I said the
rows
parameter is the rows for that group. You can access therows
data like any other array of rows usingrows()
. You can userows[0]
to access the first row of the group, for example.Kevin
I tried something like this:
and unfortunately, it doesn't populate anything to the table.
Do I need to wrap that in a
and call rows[i]?
@kthorngren I have tried to create a static working example here https://jsfiddle.net/cys1g50u/3/,
but it is grouping the items as "No group" nested with a "No group"? Why is that
The problem with your example is you are using array based data but defined the
rowGroup.dataSrc
with object notation. Fixed it here:https://jsfiddle.net/h3po15kd/
rows.count
should berows.count()
to call thecount()
API.Kevin
So I made the adjustment in response to your response https://jsfiddle.net/nb9dp1tq/. And all this does is only populate IT the IT row, but does not add the green class nor does it allow me to expand the parent?
Not sure why you are using the for loop. I changed your example to look like my suggestion:
https://jsfiddle.net/foceuspa/
The rowGroup now works properly and something is returned for the case to add the class or not. However the row is not green. So instead of using
addClass("green");
for thetr
you will need to add the class to thetd
in the row, like this:Kevin
@kthorngren since I can't call the data to addClass to the whole row, can I use data to color code the day of the week columns (Monday - Thursday). If MondayStatus = P (green), color the monday column green. So on and so forth for each other day of the week. And then from this, if all employees are green on monday, then to color the row with
.append('<td class="green" colspan="8">' + group + ' (' + rows.count() + ')</td>')
Are you wanting to look at all the rows in the group to determine the color to apply? If so you can use
rows().every()
, like this:https://jsfiddle.net/t36on5mv/
You just need to structure the HTML you return in a way that allows you to apply the CSS to the desired columns. There are no restrictions.
Kevin
@kthorngren so in this previous example, I am using a different way to style the rows than how I actually need to style them.
This was how I originally was styling the parent row. But this isn't what I need to accomplish. If you see in this new fiddle, https://jsfiddle.net/0yrcwzeh/ I am using a bunch of conditionals in the "createdRow" to color each day based on what the Status is. I then want to under each group, depending on how many sub cells are colored green, style the parent row either green yellow or red.
The fiddle isn't manipulating the static data for some reason in the child rows, so here is a screenshot of what it looks like in my actual application:
I haven't decided if it will go day by day (only count monday on the monday, then only tuesday on the tuesday, etc. so on and so forth). But right now I am just going to go off of the whole week. How can I call like in my example above with the conditional around the return, for IT the parent row would be styled green because 80% of the colored columns are green (> 75% means parent row green, >50% & <75% ,means yellow, <50% means color the row red.)
Am I even able to call those sub columns/rows or is that not achievable. I know I can call the group/parent variables but idk about the individual cells
I don't know why I haven't thought of this as an option either yet, so I am thinking depending on the cells that are green, appropriately style the Name row and then based off the name rows, we can then appropriately style the parent Department row.
I have surfed this site quite a bit and have been trying to find what the correct API reference would be in which I need to utilize here. https://datatables.net/reference/api/cells().nodes()
Is this the right direction?
In
rowGroup.startRender
you have this loop which loops through each group'sapi row().nodes()
And you have this loop which loops through each group's
row()
, specifically it gets therow().data()
.In either loop you can compile the data percentages to apply to the RowGroup
tr
.Because your actual application uses object data but your test case uses arrays. Instead of
data.MondayStatus
you would use something likedata[5]
:Kevin
@kthorngren Hello. So I was reading your response, sorry I have been extremely slammed.
I was confused when I read this part, because the function you mention underneath of it I am not using?
Or is that because you are telling me that is what I can implement within the >! >! rowGroup.startRender function?
I was thinking something along the lines of
I know that is not exactly it, and now the more I think about it I don't think this would work. I have been stuck on this for a few days now and its starting to get under my skin haha
Hello,
So I have been still trying to solve this and I am not having the best luck.
Here is my test case UPDATED: https://jsfiddle.net/BeerusDev/nzxr1gL2/11/
So I was trying to manipulate the data within the
rows.every function
, since I can't access the class of each DayStatus (i.e. 'green', 'yellow', 'red'). I wanted to see if I could access that so if the cells in the row are a certain color, I can do some math to determine how to color/addClass to the level 0 group.So it seems that all I can do is access the data in which I already used in my createdRow function? I am confused.
They are separate processes. The
rowGroup.startRender
function doesn't know anything about what you did increatedRow
.You can use
api row().node()
to get the HTML if you prefer. I added this to your example to show:One of the biggest problems you have is that your production code uses objects but your example uses arrays. You keep mixing the syntax which is probably the biggest hurdle you have. Instead of
if(data.MondayStatus == "P"){
your example needs to useif (data[7] === 'P') {
since your example is using arrays.You can's add the class to the
group
variable usinggroup.addClass('green');
. You need to add it to thetr
ortd
that is returned at the end ofstartRender
. Initialize a variable with an empty string before the loop. Within the loop determine the class you want and store that in the variable. UseaddClass()
to add that class to thetr
ortd
.Simply adding the class doesn't color the
tr
green. That class is overridden by Datatables CSS. You need to inspect thetr
to see what is applying the color, in this case it is this:You will need to use something like this in your CSS to :
See this example:
https://jsfiddle.net/7683vp0h/1/
Kevin
Kevin, my apologies it is just running circles around my head switching back and forth from object to array structured data. I read over your response and tried implementing that into my Fiddle. When I try to do what the example is doing in the fiddle you linked, it posts the absolute child row and styles that how it was, but the collapsibleparent[] rows are no longer visible? https://jsfiddle.net/BeerusDev/nzxr1gL2/18/
It gives me two errors:
"jQuery.Deferred exception: group.addClass is not a function"
&"Script error."
. I checked my JS in JSHint and their were no errors so I am confused?Sorry, this line should have been commented out:
group.addClass('green'); // This won't work. Add the class to the TR below
As I mentioned before this won't work. See the updated
https://jsfiddle.net/nase2uyv/
Kevin
Kevin,
Is the collapsible rows acting really buggy and slow for you as well? I am not sure why I am experiencing that
Wonder if its all the console.log statements.
Kevin
@kthorngren good point