Reputation: 20435
I have a Rails 4 app, which uses Turbolinks
. My understanding is that Turbolinks
breaks jQuery code, as Turbolinks does not load new page, but only get new elements.
Therefore, navigating to new page may not trigger .ready
, although it always triggers .page:load
, and thus new jQuery code won't initialize.
I have a lot of jQuery code, so I don't want to modify my jQuery code to be compatible with Turbolinks.
Is it possible to add a javascript code to my application.js that overwrites .ready
event to include page:load
as well? How should I do it?
Upvotes: 5
Views: 6513
Reputation: 9009
TLDR; Here is how the conventional approach works
$(document).ready(function() {
$("#tbl-account").tableSorter();
});
It uses jQuery to initialize a table-sorting plugin once the document finishes loading. One noticeable thing here is not teardown and re-run of this js when page component switches by Turbolink. There isn't any. There didn't need to be back in the day because the browser handled the cleanup. However, in a single-page application like Turbolinks, the browser doesn't handle it. You, the developer, have to manage the initialization and cleanup of your JavaScript behaviors.
When people try to port traditional web apps to Turbolinks, they often run into problems because their JS never cleans up after itself.
All Turbolinks-friendly JavaScript needs to:
The events for initialization are a little more complicated. We want our event handler to runs:
// Called once after the initial page has loaded
document.addEventListener(
'turbolinks:load',
() => Components.loadAll(),
{
once: true,
},
);
// Called after every non-initial page load
document.addEventListener('turbolinks:render', () =>
Components.loadAll(),
);
Thanks to Starr Horne for writing the article on migrating from jquery/pjax to turbolinks
Upvotes: 0
Reputation: 23
i had to use the page:change
event:
js:
$(document).on('page:change', function () {
<code here>
});
coffee script:
$(document).on 'page:change' ->
<code here>
Upvotes: 2
Reputation: 533
With TurboLinks 5 / Rails 5 ... I would recommend instantiating DataTables like this.
It will prevent the heading and footer paging from showing up multiple times when the back button is used.
$(document).on 'turbolinks:load', ->
tableElementIds = [
'### TABLE ID HERE ###'
]
i = 0
while i < tableElementIds.length
tableElementId = tableElementIds[i]
if $.isEmptyObject($.find(tableElementId))
i++
continue
table = undefined
if $.fn.DataTable.isDataTable(tableElementId)
table = $(tableElementId).DataTable()
else
table = $(tableElementId).DataTable(### OPTIONS HERE ###)
document.addEventListener 'turbolinks:before-cache', ->
table.destroy()
return
i++
return
Upvotes: 1
Reputation: 20531
With turbolinks 5.0.0, the events changed to turbolinks:load
. See full list of turbolinks events.
The documentation recommends following code:
document.addEventListener("turbolinks:load", function() {
// ...
})
The jquery.turbolinks fork located at https://github.com/dalpo/jquery.turbolinks already reflects these changes and allows for a seamless drop-in of turbolinks. Nevertheless, I would go for the turbolinks:load
event to have full control and not require another library.
Upvotes: 4
Reputation: 11499
Rather than wait for $(document).ready
to fire for your jQuery, just use page:load
instead:
$(document).on 'page:load' ->
<your code>
Alternatively, you can set up the jquery.turbolinks gem: https://github.com/kossnocorp/jquery.turbolinks
Upvotes: 3