Dave Dave - 1 year ago 54
CoffeeScript Question

Why isn't my coffee script function defined when I visit my page via a "link_to" link?

I’m using Rails 4.2.7. On a particular page (/users/edit), I have this link

<%= link_to "Cancel", {:controller => :my_objects, :action => 'index' }, :class => 'btn' %>

when I click on the link, I’m whisked away to the right page, in which I have a coffee script that is supposed to be executed. It contains this

$ ->
#("#add_form).click ->
console.log(" invoking function load. ")

setup_save_behavior = () ->
$("a.modal_button").click ->
# Setup action
$('#new_my_object').attr('action', '/my_objects/create')
# Clear existing error messages
# Clear existing form elements
.not(':button, :submit, :reset')

What is strange is that when I click on my link above, I get the JS error on the page

my_objects.self-50d1edb….js?body=1:16 Uncaught TypeError: setup_save_behavior is not a function

even though the console.log is executed (I can see " invoking function load. " printed out). If I actually go into my URL’s address bar and then type my URL, “http://loclahost:3000/my_objects/index,” then everything loads fine and there are no Javascript errors. I’m totally baffled. What can I do so that my function gets defined when I click on the link defined by the “link_to” script?

Answer Source

Turbolinks can cause problems in your Rails app because it tries to save overhead by maintaining assets listed in the <head> element of your page (among other things). When you load a page using a full load (via refresh button), an actual ready event takes place and your scripts work. On the other hand, if you were to visit a page some other way (via link), Turbolinks tries to reuse the <head> element, so there's no ready event fired.

The solution in the past was to simply disable Turbolinks, either entirely, by removing its require line in application.js or by link (data: {no_turbolink: true}). With Rails 4.2.x and 5.x, you can listen for a Turbolinks related event that should work where a normal ready event would have worked before.

From the documentation:

However, because Turbolinks overrides the normal page loading process, the event that this relies on will not be fired. If you have code that looks like this

$(document).ready ->
  alert "page has loaded!"

you must change your code to do this instead:

$(document).on "turbolinks:load", ->
  alert "page has loaded!"

(quote rearranged slightly for clarity)