Sticky sorting of row groupings

Sticky sorting of row groupings

michalakmjmichalakmj Posts: 4Questions: 1Answers: 0

I am a bit stuck on which approach is best for solving my requirements. What I am trying to do is group data together into groups and then keep those groups together when any of the columns are sorted. First, let me describe my environment: I am sourcing the data in my DataTable with DOM as I am also using CanJS and a Mustache template.

What I started with is taking the row grouping example found at https://datatables.net/examples/advanced_init/row_grouping.html. Great example – this got me quite a bit along the way of where I need to go.

I then looked at different ways to see how I can keep the data grouped together when it is sorted. For example, sort the data in the example by age. The first three entries are 19 (London), 20 (Tokyo), and 21 (London). What I need to happen is that since London is the first youngest, display all of the London data first. Then since Tokyo is next, display all of the Tokyo data next. The closest I have gotten looking through and trying a few of the options is “orderFixed”. The pre parameter is what works the best, as it keeps the data together in the group. However, since it locks in the group into the order, the first group you will always see is Edinburgh.

Not seeing a solution that works for me in the forums, I have been able to solve sticky group sort issue with some extra JavaScript in the drawCallback method. I have placed that code here - http://live.datatables.net/secojixi/1/edit?html,css,js,output. You will see the JS that I added separated by some ‘//-----‘ comments.

My next challenge is handling updated data to the table. Imagine there is another column that gets updated by a service call separate from the rest of the data. The order is that the data seen with the examples is displayed first, then the other column later. I am having a difficult time trying to figure out how to get that data to display and still keep the logic for “sticky group ordering” around. If I keep the JS around that I created in the above DataTables live clip, I never see the data when it is added to the DOM even though I know it is there. If I take out that code, I see the data but I am not able to keep the groupings together when I sort.

I have tried invalidating the data in the rows to no success. I’m sure my problem is either user error or ignorance, possibly both.

This question has an accepted answers - jump to answer

Answers

  • allanallan Posts: 63,179Questions: 1Answers: 10,410 Site admin

    One option might be to use orderFixed - that way you can specify a sort that will always be performed prior to a user's sort (i.e. you would sort by your grouping column).

    The one downside to this is that it won't automatically inverse the sorting direction when the user click to invert (asc v desc). A click event handler on the header cells would be needed for that, in combination with order.fixed().

    Allan

  • michalakmjmichalakmj Posts: 4Questions: 1Answers: 0

    Thanks for the reply. I have tried the orderFixed option, but I need the column identified in the orderFixed to group the data together as it is sorted up and down a table vs. held in the same place.

    One of the interesting things I have noted is that with the JS solution I have created is how the data gets set with the following code:
    api.rows().every(function (rowIdx, tableLoop, rowLoop) {
    this.data(dataRows[officeGroupArray[rowLoop]]); <---
    });

    Once the line of code “this.data(…)” is executed, the data seems to be very much set by DT. No matter what updates happen to the DOM on the backend, the API for the datatable will always return the same data. If I comment the “this.data(...)” line out, I see all of the data updates (but the sticky group sorting is gone).

    Reading thru the documentation, I see that DT caches the contents of each cell for performance. The trick then is getting DT to realize there is updated data. The obvious choice is to use invalidate(), but that doesn't seem to do the trick. I have also tried playing around with the state of the table without any success either. Is there a better way to set or flush the data that DT holds in its cache with updated DOM data?

    I know this is more of a DataTables 101 question. I think I have my sticky group sort thing figured out with my custom code, now it is a matter of getting that integrated with data changes.

  • allanallan Posts: 63,179Questions: 1Answers: 10,410 Site admin

    row().invalidate() is the correct want to tell DataTables to clear its cache for a row. I'm not sure why that wouldn't work for you.

    If orderFixed basically does the job for you, but you need it to work for inverted data as well, that should be possible with a click event handler as I suggested above (although admittedly it isn't something I've tried myself yet).

    Allan

  • michalakmjmichalakmj Posts: 4Questions: 1Answers: 0

    I think the reason why the invalidate function isn't working is how the data updates are getting placed on the page. Since I am using CanJS and Mustache templates, I am not directly setting data into the DataTable, but instead on the JavaScript objects that the mustache template uses to display the information. That is probably why using rows().invalidate() or row().invalidate() is not working in my case – after initialization and the data is set into cache using this.data(), all data changes are handled outside of the DataTables API. If I change the data source from DOM to Javascript, the changes happen right away but I need to format the HTML inside Javascript and I can’t seem to get two-way bindings to work.

    I see there is a similar thread around mustache templates and DataTables that sounds similar to the issue I am having (https://datatables.net/forums/discussion/30686/mustache-support). I will read up on that one a bit more to see if that helps out. If I stumble upon something else, I will post it here for reference.

  • michalakmjmichalakmj Posts: 4Questions: 1Answers: 0

    It turns out that the best solution that I was able to get to work was to mimic the sorting of columns by DT through my own JS code and update the data held in the API. I created a separate hidden column in my table where I controlled the sort order. Once this was updated, a quick call to invalidate().draw() took care of the page being sorted correctly.

  • allanallan Posts: 63,179Questions: 1Answers: 10,410 Site admin
    Answer ✓

    Sounds good - thanks for posting back - much appreciated!

    Longer term, this is certainly something that needs to be improved in DataTables.

    Allan

This discussion has been closed.