Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I prevent duplicate wrappers on a jQuery DataTable when navigating back in the presence of Turbolinks?

I'm using jQuery DataTables in a new Rails 4.2 project. I've got a large number of results that need to be filtered on group, project, and status. Choosing the group filters the project selection, via a roundtrip through the application, and the project selection filters the table the same way. I save the group & project in session variables so that, when the user changes pages, then clicks the main link to come back, it will remember their selection, and get them back to where they were. This all works like I intend it to.

The problem is that using the browser's back button to get back to the table from a different page will result in a duplicate wrapper (with search box, number-of-items dropdown, and pagination links) around the DataTable.

enter image description here

I've added the jquery-turbolinks gem.

I've tried fiddling with event listeners, but I can't make either of those ideas work.

I've tried making the body of the page exempted from Turbolinks with data-turbolinks=false.

I've tried changing the event my script(s) key on to something other than $(document).ready(), like page:load. None of them prevent this.

I've tried loading all the scripts for the DataTable as exempted from Turbolinks with data-turbolinks-eval=false in that specific page (with content_for :head).

The only thing I've found that will prevent this wrapper duplication from happening is to simply remove the call to include the turbolinks JS from the assets entirely. And I'd have done this already if I didn't know that smarter people than me think it ought to be a part of the application. I don't know what to do. I'm looking for the elegant way to handle this.

UPDATE: Four years later, I'm using Rails 6.1, and still using Ag-Grid extensively. I'd like to try the new hotness from Rails Hotwire, but it seems to be built on Turbolinks. So I've taken another pass at getting Ag-Grid to play nicely with Turbolinks, and it still has all the same problems as DataTables, and I STILL can't figure out a way forward with it.

I got some small progress with a tip from this page on DataTables, by putting data-turbolinks="false" in the div for the table (not the page, like I had previously tried). For some navigation, this "worked." By "worked," I mean that it prevented duplicating the table, but it still reloads the whole table.

I also found this fascinating discussion about how Basecamp apparently deals with the cache in the presence of Turbolinks, but it didn't help for Ag-Grid.

I've discovered that the right incantation to prevent duplication of table elements is to use document.addEventListener('DOMContentLoaded', function() {}) as my key. It seems to respect all the different cases of using links or back/forward buttons for navigation, without duplicating. However, I'm losing any rows in the table past what is showing on the screen, and the whole table needs to have data fetched and displayed again, anyway, so that really doesn't solve anything.

That's the part that continues to fascinate and frustrate me about this situation. If I DON'T use Tubolinks, these JS tables work GREAT with the browser navigation buttons. I can page back and forward, and none of the data has to get reloaded. If I DO use Turbolinks, and manage to prevent the duplication of the table elements, I need to reload the table data. I'm clearly getting caught in the middle of 2 different JS caches, and after 4 years, I still can't figure out how to get them to play nicely together.

like image 289
David Krider Avatar asked Oct 17 '22 21:10

David Krider


1 Answers

My table works as I expect with the following settings.

For datatable.js or application.js.

var dataTable = null

document.addEventListener("turbolinks:before-cache", function() {
  if (dataTable !== null) {
   dataTable.destroy()
   dataTable = null
  }
})

For view.

<table id="my-table">
  ..
</table>

<script>
  dataTable = $('#my-table').DataTable({
    stateSave: true
  })
</script>

References:

  • Turbolinks 5 and DataTables working together in harmony
  • browser back button causes some scripts to reevaluate
like image 76
asukiaaa Avatar answered Oct 21 '22 05:10

asukiaaa