80

I'm having some trouble loading my javascript when I use a link_to helper in rails. When I either manually enter the url with 'localhost:3000/products/new' or reload the page, the javascript loads, but when I go through a link as written below, the jQuery $(document).ready will not load on the new page.

Link_to, javascript does not load when I click this link:

<%= link_to "New Product", new_product_path %>

products.js file

$(document).ready(function() {
    alert("test");
});

Any help would be much appreciated. Thanks in advance!

Ryan Endacott
  • 8,772
  • 4
  • 27
  • 39
StickMaNX
  • 1,982
  • 2
  • 16
  • 13

8 Answers8

142

Are you using Rails 4? (Find out by doing rails -v in your console)

This issue is probably due to the newly added Turbolinks gem. It makes your application behave like a single page JavaScript application. It has a few benefits (it's faster), but it unfortunately breaks some existing events like $(document).ready() because the page is never reloaded. That would explain why the JavaScript works when you directly load the URL, but not when you navigate to it through a link_to.

Here's a RailsCast about Turbolinks.

There are a couple solutions. You can use jquery.turbolinks as a drop-in fix, or you can switch your $(document).ready() statement to instead use the Turbolinks 'page:change' event:

$(document).on('page:change', function() {
    // your stuff here
});

Alternatively, you could do something like this for compatibility with regular page loads as well as Turbolinks:

var ready = function() {
    // do stuff here.
};

$(document).ready(ready);
$(document).on('page:change', ready);

If you are using Ruby on Rails >5 (you can check by running rails -v in the console) use 'turbolinks:load' instead of 'page:change'

$(document).on('turbolinks:load', ready); 
Anthony Wood
  • 395
  • 1
  • 3
  • 16
Ryan Endacott
  • 8,772
  • 4
  • 27
  • 39
  • Yes, this is Rails 4. What you posted does fix it through link_to clicks. It also makes it not work on regular manual url page loads, is there a way to make it work through both methods without duplicating my js code? Thanks! – StickMaNX Jul 11 '13 at 18:00
  • 1
    Hmm, that's odd. I would think it would work for both. The best solution is to probably use the linked jquery.turbolinks gem, because it probably handles that as well. Note: I haven't used it so I'm not certain. It looks like it rebinds `'page:load'` to call `$(document).ready()` though, so you would just do everything as normal. – Ryan Endacott Jul 11 '13 at 18:01
  • I edited my answer to make a solution that should work without jquery.turbolinks :) – Ryan Endacott Jul 11 '13 at 18:05
  • Editing all the code in every js file, which expects document.ready to work as it always has, is not an option for an app of any size and complexity. Why would someone design something that makes document.ready not work as it always has, and call that a feature? Is there a way to just tell turbolinks not to break document.ready - or is the only option to uninstall it? – JosephK Oct 06 '16 at 05:18
  • It is a pretty unfortunate change. I'm not sure why they decided to break such common behavior. I believe you can just use [jquery.turbolinks](https://github.com/kossnocorp/jquery.turbolinks) as a drop-in fix though, and everything will work normally. – Ryan Endacott Oct 11 '16 at 21:09
  • For no jQuery developers `document.AddEventListener('turbolinks:load', function(){...})` fix the iusse. – alex Jul 05 '19 at 20:49
66

I got the same probleme but jquery.turbolinks doesn't helped. I noticed that I have to override the GET method.

There is my sample :

<%= link_to 'Edit', edit_interpreter_path(@interpreter), method: :get %>
Ice-Blaze
  • 897
  • 8
  • 18
  • 2
    This was the fastest solution to implement. – Jose Torres Sep 15 '15 at 16:20
  • 1
    This solved the problem for that `link_to` but turns out the real issue was an inline ` – poorman Nov 11 '15 at 18:20
  • 1
    The best solution is to remove turbolinks, imo. Fixing things that should "just work" with "work-arounds" is a huge time-killer. I could have taken a week off last year from turbolinks-fixes, alone. – JosephK Oct 06 '16 at 04:52
  • 1
    this made my day ! –  Oct 03 '17 at 12:33
  • Good answer for fast-fix, but for an optimal solution see the answer of @RyanEndacott – dimpiax Mar 03 '19 at 22:26
25

If you are on rails 5 instead of 'page:change' you should use 'turbolinks:load' like this:

$(document).on('turbolinks:load', function() {
  // Should be called at each visit
})

Source: https://stackoverflow.com/a/36110790

Community
  • 1
  • 1
user000001
  • 32,226
  • 12
  • 81
  • 108
  • This and Ice-Blaze's solution both worked for me. But I like this best since I don't have to change all my links. (I am using Rails 5) – Sean May 14 '17 at 04:03
5

You can also wrap your link with a div that specifies data-no-turbolink.

Example:

<div id="some-div" data-no-turbolink>
    <a href="/">Home (without Turbolinks)</a>
</div>

Source: https://github.com/rails/turbolinks

equn
  • 73
  • 1
  • 4
3

Make sure you don't have any inline <script> tags. (Inline script tags are bad with turbolinks).

poorman
  • 120
  • 7
3

FWIW, from the Turbolinks docs, the more appropriate event to capture instead of the $(document).ready is page:change.

page:load has a caveat that it doesn't fire on cache reloads...

A new body element has been loaded into the DOM. Does not fire on partial replacement or when a page is restored from cache, so as not to fire twice on the same body.

And since Turbolinks is just switching the view, page:change is more appropriate.

pyepye
  • 156
  • 1
  • 6
0

The solution that solved my issue was adding this meta property.

<meta name="turbolinks-visit-control" content="reload">

This ensures visits to a certain page will always trigger a full reload.

This was incredibly useful for working on a solution to solve the issue I was having with this, https://github.com/turbolinks/turbolinks#reloading-when-assets-change .

Rockwell Rice
  • 3,376
  • 5
  • 33
  • 61
-1

If your link_to js is working after reload so it should be a turbolink issue, you can use turbolink false on that link_to like for ex:

<%= link_to "Home", home_path, data: { turbolinks: false } %>
lissettdm
  • 12,267
  • 1
  • 18
  • 39
MD Shahid Khan
  • 670
  • 4
  • 5