Using the TableLoop of rows.every() To Loop Through Every Row

Using the TableLoop of rows.every() To Loop Through Every Row

zgoforthzgoforth Posts: 493Questions: 98Answers: 2
edited June 2021 in DataTables 1.10

Link to test case: https://jsfiddle.net/BeerusDev/03un1aLc/66/

Hello, currently I am utlizing my startRender and endRender to loop through each rowGroup to get a count of each status for that day. I realized this is actually not what I need to do. I am so close, yet I feel so far. I was looking at the rows.every() page again, and came across something I thought I may found useful, tableLoop as opposed to rowLoop. From my understanding, rowLoop is going through everything that is within each rowGroup, but tableLoop should loop through every row in the table correct?

I keep getting requirements changed, so this is the final piece of the puzzle I need to solve. Can I use the tableLoop to loop through the whole table and provide a count of all of the counts for the statCount values at the table footer? Instead of a row footer?

I have been unable to find any examples on the tableloop in work

Answers

  • kthorngrenkthorngren Posts: 21,330Questions: 26Answers: 4,951

    The tableLoop parameter won't do what you think. It doesn't control the data that is looped. Its useful if you are looping more than one table to give an index of the table being looped. You are doing this:

    rows.every(function ( rowIdx, tableLoop, rowLoop, data ) { ... });
    

    The rows variable is from the startRender parameter rows which are the rows for the particular group being displayed. If you want to loop all of the rows for each group then you will need to get an instance of the API, var table = $('#myTable').DataTable(); for example, then replace rows.every(...) with table.every(...).

    Kevin

  • kthorngrenkthorngren Posts: 21,330Questions: 26Answers: 4,951

    Actually you will need to use table.rows().every(...).

    Kevin

  • zgoforthzgoforth Posts: 493Questions: 98Answers: 2
    edited June 2021

    Is it possible to keep the startRender (I need that to determine the styling applied to each row group), with out it, I will lose a lot of functionality of my table itself. If I call a new instance of the API anywhere, can I accomplish this outside of my rowGroup? That way I can use the data outside of the rowGroup function and append it to my <tfoot>

    https://jsfiddle.net/BeerusDev/vzehsqn8/12/

  • kthorngrenkthorngren Posts: 21,330Questions: 26Answers: 4,951
    edited June 2021

    You can use that API at anytime you like. Maybe in the footerCallback is when you want to use it.

    Kevin

  • zgoforthzgoforth Posts: 493Questions: 98Answers: 2
    edited June 2021

    Sweet, I have .draw in the AJAX loadData at the beginning of the JS, as well as one in my $("div.toolbar").html, followed by $('#myTable tbody').on('click', 'tr.dtrg-start', function() { are those the correct .draw()'s or do I need to create a new draw function like on line 591 in my JS Fiddle: https://jsfiddle.net/BeerusDev/vzehsqn8/17/

    I tried just repeating this:

    var table = $('#myTable').DataTable();
                table.on( 'draw', function () {
                var statCount = {P: 0, TW: 0, NR: 0, TRV: 0, PTO: 0, H: 0 };
                table.rows.every(function(rowIdx, tableLoop, rowLoop, data){
                    var data = this.data();
                    var today = moment().format("YYYY-MM-DD");
                        
                    var result = Object.keys(data).find((key) => typeof data[key] === "string" && data[key].startsWith(today)); // "Monday;
                        //console.log(result);
                    var todayStatus = result ? data[result + "Status"] : "n/a";
                        //console.log(todayStatus);
    
                        if (todayStatus === "P") {
                            statCount.P++;
                        }
                        if(todayStatus === "TW"){
                            statCount.TW++;
                        }
                        if (todayStatus === "NR") {
                            statCount.NR++;
                        }
                        if(todayStatus === "TRV"){
                            statCount.TRV++;
                        }
                        if (todayStatus === "PTO") {
                            statCount.PTO++;
                        }
                        if(todayStatus === "H"){
                            statCount.PTO++;
                        }
                        console.log(statCount);
                })
            });
    

    But, nothing console logs and I don't think it is actually getting any of the data. That way, if this does what it is supposed to do (count the total count through all rows) I can use something like jQuery to append the total counts for the day to the tfoot

  • zgoforthzgoforth Posts: 493Questions: 98Answers: 2

    My apologies on the last comment I didnt see you changed the draw to footerCallback: https://jsfiddle.net/BeerusDev/vzehsqn8/26/ Here is where I am trying to use my footerCallback

  • kthorngrenkthorngren Posts: 21,330Questions: 26Answers: 4,951

    You need to add the footer tr and th elements for this to work:

    $(tfoot).find('th').eq(0).html( result + ": Result  ");
    

    You need to move the footerCallback outside the rowGroup options so that it runs.

    Kevin

  • zgoforthzgoforth Posts: 493Questions: 98Answers: 2

    When I add the footer <tr> and <th> tags, as well as moved my footerCallback outside of my rowGroup option. When I do this (only the tfoot <tr> & <th> tags cause it), the table doesn't load and I get the following error:
    "jQuery.Deferred exception: Cannot read property 'nodeName' of null", "TypeError: Cannot read property 'nodeName' of null

    Here is my up to date Fiddle: https://jsfiddle.net/BeerusDev/vzehsqn8/37/

  • kthorngrenkthorngren Posts: 21,330Questions: 26Answers: 4,951

    Datatables expects to find a th for each column in the footer to allow things like column().footer() to work properly.

    Kevin

  • zgoforthzgoforth Posts: 493Questions: 98Answers: 2
    edited June 2021

    Hello,

    https://jsfiddle.net/BeerusDev/vzehsqn8/49/

    So I went ahead and fixed that with the following:

    <tr>
      <th colspan="12" style="text-align:center">Total:</th>
    </tr>
    

    After reading through all of the examples I can find as well as discussion posts, it seems the common consensus is that integer data must be contained in the column(s) for it to work? Please tell me this is incorrect, I should be able to create a count of each value in the columns I want to include (or table as a whole) while filtered. In my footer you can see the Total: which is where I want the count of all the current week status to show.

    https://www.datatables.net/forums/discussion/45385/footer-callback-for-multiple-columns

    In this thread, markzz asked about the filter functionality. Is this possible? The way my filter works if you search a date that's in between Monday and Friday it will pull up all items associated with that week.

  • kthorngrenkthorngren Posts: 21,330Questions: 26Answers: 4,951

    it seems the common consensus is that integer data must be contained in the column(s) for it to work?

    I'm not sure what you are referring to. This example uses the intVal() function to sanitize the salary values into integers because that is what they are. There is no requirement or limitation. You need to adjust the code in the footerCallback to properly handle the data type you have.

    In this thread, markzz asked about the filter functionality. Is this possible?

    You can use the selector-modifier of { search:'applied' }.

    Kevin

  • zgoforthzgoforth Posts: 493Questions: 98Answers: 2

    Before I can even do anything, I get the error
    "jQuery.Deferred exception: table.rows.every is not a function", "TypeError: table.rows.every is not a function

    https://jsfiddle.net/BeerusDev/vzehsqn8/66/

  • kthorngrenkthorngren Posts: 21,330Questions: 26Answers: 4,951

    Use this.api() like the exmaple has instead of var table = $('#myTable').DataTable(); to get the API instance.

    Kevin

  • zgoforthzgoforth Posts: 493Questions: 98Answers: 2

    That returns a new jQuery deferred error: Cannot read property 'rows' of undefined", "TypeError: Cannot read property 'rows' of undefined

    https://jsfiddle.net/BeerusDev/vzehsqn8/71/

  • kthorngrenkthorngren Posts: 21,330Questions: 26Answers: 4,951
    edited June 2021

    Instead of table you need to use the api variable for access to the API. Also you need to use rows().every() not `rows.every(). Like this:

                "footerCallback": function( tfoot, data, start, end, display ) {
                 var api = this.api(), data;
                          api.rows().every(function (rowIdx, tableLoop, rowLoop, data){
                          
                          });
                                                                      
            },
    

    Kevin

  • zgoforthzgoforth Posts: 493Questions: 98Answers: 2

    https://jsfiddle.net/BeerusDev/vzehsqn8/97/

    "jQuery.Deferred exception: Cannot read property 'MondayStatus' of undefined", "TypeError: Cannot read property 'MondayStatus' of undefined

  • zgoforthzgoforth Posts: 493Questions: 98Answers: 2

    https://jsfiddle.net/BeerusDev/vzehsqn8/110/ This is the updated one, my comment did not update for some reason. I have used the table.rows() and that works, but when I try what I am doing with the api.rows().every(), I get data as undefined and nothing will post with what I have, but even with table.rows() it recognizes the MondayStatus, but data is still undefined? I do not understand

Sign In or Register to comment.