Problem presumably related to row().invalidate()

Problem presumably related to row().invalidate()

kc5151kc5151 Posts: 50Questions: 4Answers: 1
edited October 1 in Free community support

Hi everyone :smile:.

I have the following use case:

My data is from multiple tables that are being joined. Most of it is 1:1 relation, but some is 1:n.

Now I want to omit the duplicate data from my Datatable, at least when it's appropriately sorted, and I'm facing some side effects.

Here's an example for what I want to do:

https://live.datatables.net/julaqeba/3/edit

The relevant stuff is in the rowCallback function.

What my example does is:

  • checking if two lines following each other have an identical Position text
  • if so, omit the Position text from all rows following the first one

This works, but I have to invalidate all rows, otherwise, when I re-sort the table, bad things happen.

Now, I have an unexpected side effect: with default ordering, you'll notice that the Salary column in the first row is right aligned while it is left aligned in all following rows.

Somehow, my row invalidation efforts are removing the dt-type-numeric class from all but the first row (in my actual application, it removes the date class etc.).

Can somebody shed some light as to why that happens or maybe I'm overcomplicating things in my approach?

Thanks bunch in advance!

This question has an accepted answers - jump to answer

Answers

  • rf1234rf1234 Posts: 2,951Questions: 87Answers: 416

    You are invalidating the entire row. Have you tried invalidating just the position column? That would be something like this:

    dataTable.cell(row, 3).invalidate();
    

    Assuming that position is column 3

  • kc5151kc5151 Posts: 50Questions: 4Answers: 1
    edited October 1

    Well, in my actual project I'm omitting text for like half the entire row. So this would probably just shift the side effect around, I guess. I feel that there must be a better approach to this problem, which I seem to be unable to find :wink: Thanks anyways!

  • kthorngrenkthorngren Posts: 21,188Questions: 26Answers: 4,925

    Not sure I understand all of what you are trying to do. Maybe the RowGroup extension will do what you want.

    Kevin

  • kc5151kc5151 Posts: 50Questions: 4Answers: 1

    The RowGroup extension looks very nice (saw it before), but it doesn't exactly do what I want. Since most of my table data is 1:1, it would add many additional rows that aren't needed, since there is only 1 element in the group.

    Maybe I could try getting it to work so that it only creates a group when there is more than 1 element in it, but I didn't see any examples for that, so I'm not sure if it's possible.

    I'll try to explain better what my original idea is: most of my data looks like this:

    OrderNumber1 - AdditionalOrderInfo1 - SomethingElse1
    OrderNumber2 - AdditionalOrderInfo2 - SomethingElse2
    OrderNumber3 - AdditionalOrderInfo3 - SomethingElse3
    

    But then I also have:

    OrderNumber4 - AdditionalOrderInfo4.1 - SomethingElse4.1
    OrderNumber4 - AdditionalOrderInfo4.2 - SomethingElse4.2
    OrderNumber4 - AdditionalOrderInfo4.3 - SomethingElse4.3
    

    When there are identical order numbers following each other, I just want to display the order number in the first row and omit it in the following rows (this is a simplified example, actually I want to "hide" the content of like half the columns of my table).

    Thanks again.

  • kthorngrenkthorngren Posts: 21,188Questions: 26Answers: 4,925
    edited October 1

    I see, I wasn't able to run the test case earlier on my phone :smile:

    Removing row().invalidate() doesn't seem to affect sorting in the test case.
    https://live.datatables.net/julaqeba/8/edit

    I'm not sure its doing anything useful for you nor do I think you want to use it as I believe i.innerHTML = ""; is intended as a temporary display of an empty cell. Meaning you don't want to change the original data.

    Can you provide steps to replicate the sorting issue?

    Kevin

  • kc5151kc5151 Posts: 50Questions: 4Answers: 1
    edited October 1

    Thanks for your time :smile:. Not calling "invalidate" makes the table go haywire (well, calling it does too, I'll get to that in a few seconds). It's a bit tricky to reproduce here, but this are the steps:

    1) sort by Name column, ascending
    2) verify that "Abbey Jobson" has "Machine Operator" as position
    3) filter the Position column for "Machine Operator"
    4) sort by Name, descending this time
    5) jump to the last page (should be page 7)
    6) "Abbey Jobson" doesn't have "Machine Operator" next to it
    7) sort by Name column, ascending, and remove search filter
    8) "Abbey Jobson" still doesn't have Position

    So, something is amiss there.

    "invalidate" makes things even worse, as I just noticed. When I uncomment

    dataTable.row(row).invalidate();
    

    again, on every keypress in a search box (even backspace) there are entries disappearing from the table (10 entries at a time, so an entire page). This seems to happen if the table is sorted by the Position column.

    So this is certainly not the solution either. I didn't notice this in my actual project, but will re-check tomorrow.

  • kc5151kc5151 Posts: 50Questions: 4Answers: 1

    I just tried the suggestion rf1234 made earlier and invalidated only the cells that I actually change. But that doesn't work either:

    https://live.datatables.net/yaxubuli/1/edit

                  if (column_name && (column_name == 'position' || column_name == 'salary')) {
                    dataTable.cell(i).invalidate();
    
                    //console.log(column_name);
                    //console.log(i.innerHTML);
                    i.innerHTML = "";
                    i.classList.remove("dt-control");
                  }
    

    This also makes rows randomly disappearing or missing content.

  • kthorngrenkthorngren Posts: 21,188Questions: 26Answers: 4,925
    edited October 1

    Thanks for the detailed steps, it helps! Looks like you need to reset the first row on the page, for example:
    https://live.datatables.net/julaqeba/9/edit

    With this each page displays the position in the top row. Not sure if that's what you want but maybe it will get you closer.

    I don't think you will want to use any of the invalidate APIs for this requirement.

    Kevin

  • kc5151kc5151 Posts: 50Questions: 4Answers: 1

    Thanks Kevin, however, your approach still has problems with cells staying blank after re-sorting. Also, it doesn't restore the rendering and class information.

    I did it like this now:

    https://live.datatables.net/kizapusa/1/edit

    This looks very messy again, but it seems like it's working.

    I'm basically manually storing the HTML and Class data before I remove it, and restore it when required.

    Maybe someone has an idea for a cleaner approach that doesn't require storing this "by hand"?

    Cheers and thanks for your help again :smile:

  • kthorngrenkthorngren Posts: 21,188Questions: 26Answers: 4,925
    Answer ✓

    Are you using storage_html to store the cell data because you are using columns.render to display the data? Instead you can use cell().render() to get the displayed cell data. This will save using one data structure.

    I updated my last example to use columns.render for the position column and cell().render() to grab the displayed cell data.
    https://live.datatables.net/nehiwabe/1/edit

    Also note you can get an instance of the DT API by using this.api(). I updated my last example to show this but forgot to point it out. For example:

    let dataTable = this.api();
    

    I didn't understand the use of i.classList.remove("dt-control"). Just thought it was an example and I didn't include it in my example because it didn't make sense to add that class to the position column. Are you trying to workaround the issue that you aren't using columns.className to assign dt-control to the first column?

    And are you only trying to add and remove the dt-control class to the first column based on whether the cell is blank or is showing the cell data?

    Assuming that is what you want I added this code:

            let dtControlFlag = dataTable.column(0).header().classList.contains('dt-control')
            if (dtControlFlag) {
              dataTable.cell(row, 0).node().classList.add("dt-control");
            }
    

    And only remove the class is the position cell is set to display an empty string.

    Kevin

  • kthorngrenkthorngren Posts: 21,188Questions: 26Answers: 4,925

    I should add that the test case also uses column().header() and cell().node().

    Kevin

  • kc5151kc5151 Posts: 50Questions: 4Answers: 1

    Thanks a bunch, I'll probably look into this next week :smile:. There's a bank holiday here tomorrow, and I took Friday off.

    Cheers!

  • kc5151kc5151 Posts: 50Questions: 4Answers: 1

    Hey Kevin. I finally got around to testing your solution. Everything worked out fine, except that there was an "else" branch missing for the if (prev_data == cur_data) condition (with the same content as the "else" branch for if (displayNum > 0)). Still, now the code doesn't as convoluted as it did before, so thanks a lot again for your time. :smile:

  • kthorngrenkthorngren Posts: 21,188Questions: 26Answers: 4,925

    I'm not sure what the else would be for but glad you got it working.

    Kevin

  • kc5151kc5151 Posts: 50Questions: 4Answers: 1

    The else is required so that the error from a few posts earlier (the 8 steps I supplied to reproduce it) does not occur, it still happens in your example :). Cheers.

  • kthorngrenkthorngren Posts: 21,188Questions: 26Answers: 4,925
    edited October 14

    Hmm, I followed those steps and it seems to be working correctly. Here is a screenshot after step 8 with Abbey Johnson having the position of Machine Operator render:

    I guess it doesn't matter if you have it working the way you want. Maybe what you want is different than what I interpreted. If you want to show us please update the test case to show the needed change as I don't know what is in the else clause you added.

    Kevin

  • kc5151kc5151 Posts: 50Questions: 4Answers: 1

    7) sort by Name column, ascending, and remove search filter

    This step was unclear, you first have to remove the search filter and then sort by Name column. But no need to further improve your example, since I have it working. The additional else branch contains the same code as the else branch for if (displayNum > 0).

    Cheers.

  • kthorngrenkthorngren Posts: 21,188Questions: 26Answers: 4,925
    edited October 15

    Cool, thanks for clarifying. I see the problem now. Here is the updated test case in case anyone else is interested:
    https://live.datatables.net/nehiwabe/3/edit

    Kevin

Sign In or Register to comment.