I ran into an issue in my Rails 4 app while trying to organize JS files \"the rails way\". They were previously scattered across different views. I organized them into separ
Found this in the Rails 4 documentation, similar to DemoZluk's solution but slightly shorter:
$(document).on 'page:change', ->
# Actions to do
OR
$(document).on('page:change', function () {
// Actions to do
});
If you have external scripts that call $(document).ready()
or if you can't be bothered rewriting all your existing JavaScript, then this gem allows you to keep using $(document).ready()
with TurboLinks: https://github.com/kossnocorp/jquery.turbolinks
NOTE: See @SDP's answer for a clean, built-in solution
I fixed it as follows:
make sure you include application.js before the other app dependent js files get included by changing the include order as follows:
// in application.js - make sure `require_self` comes before `require_tree .`
//= require_self
//= require_tree .
Define a global function that handles the binding in application.js
// application.js
window.onLoad = function(callback) {
// binds ready event and turbolink page:load event
$(document).ready(callback);
$(document).on('page:load',callback);
};
Now you can bind stuff like:
// in coffee script:
onLoad ->
$('a.clickable').click =>
alert('link clicked!');
// equivalent in javascript:
onLoad(function() {
$('a.clickable').click(function() {
alert('link clicked');
});
I usually do the following for my rails 4 projects:
In application.js
function onInit(callback){
$(document).ready(callback);
$(document).on('page:load', callback);
}
Then in the rest of the .js files, instead of using $(function (){})
I call onInit(function(){})
Here's what I have done to ensure things aren't executed twice:
$(document).on("page:change", function() {
// ... init things, just do not bind events ...
$(document).off("page:change");
});
I find using the jquery-turbolinks
gem or combining $(document).ready
and $(document).on("page:load")
or using $(document).on("page:change")
by itself behaves unexpectedly--especially if you're in development.
As per the new rails guides, the correct way is to do the following:
$(document).on('turbolinks:load', function() {
console.log('(document).turbolinks:load')
});
or, in coffeescript:
$(document).on "turbolinks:load", ->
alert "page has loaded!"
Do not listen to the event $(document).ready
and only one event will be fired. No surprises, no need to use the jquery.turbolinks gem.
This works with rails 4.2 and above, not only rails 5.
Recently I found the most clean and easy to understand way of dealing with it:
$(document).on 'ready page:load', ->
# Actions to do
OR
$(document).on('ready page:load', function () {
// Actions to do
});
EDIT
If you have delegated events bound to the document
, make sure you attach them outside of the ready
function, otherwise they will get rebound on every page:load
event (causing the same functions to be run multiple times). For example, if you have any calls like this:
$(document).on 'ready page:load', ->
...
$(document).on 'click', '.button', ->
...
...
Take them out of the ready
function, like this:
$(document).on 'ready page:load', ->
...
...
$(document).on 'click', '.button', ->
...
Delegated events bound to the document
do not need to be bound on the ready
event.