Adding Javascript to Rails 6
Hi. I am fairly new to Rails and so far I have been unsucessful at adding any JS to my Rails 6 project. I have seen many videos and tutorials but i seem to run in to the same issue. Basically I get "xxx is undefined" for every script. I'm thinking my scripts are called at the wrong time or in the wrong order. I'm using Webpacker for my JS. Thanks
Hey Tom,
You'll have to share what you've got so we can help. If you can push up a repo to github, that would be most helpful. Otherwise just post your steps to reproduce the issue and we'll get you sorted. 👍
Sure, so for example. I am trying to add Toastr. I have installed via Yarn.
In my javascript/packs/application.js I have require("toastr")
I also have an application_helper.rb which i saw from a tutorial about adding Toastr so i have:
def toastr_flash
flash.each_with_object([]) do |(type, message), flash_messages|
type = 'success' if type == 'notice'
type = 'error' if type == 'alert'
text = "<script>toastr.#{type}('#{message}', '', { closeButton: true, progressBar: true })</script>"
flash_messages << text.html_safe if message
end.join("\n").html_safe
end
Then I call toastr_flash
in my views/layouts/application.html.rb.
The error i get is Uncaught ReferenceError: toastr is not defined
Any direction is appreciated.
Hey Tom,
That would be giving you the error because Javascript with inline script tags (that your helper is generating) are executed immediately. It does not wait for your webpacker Javascript to finish loading toastr before it runs. Hence the error.
You will want to wrap your code in a turbolinks:load event so that it waits until Turbolinks is ready and all your JS is loaded before it executes.
Example code I forgot to paste:
def toastr_flash
flash.each_with_object([]) do |(type, message), flash_messages|
type = 'success' if type == 'notice'
type = 'error' if type == 'alert'
text = <<~EOF
<script>
document.addEventListener("turbolinks:load", function() {
toastr.#{type}('#{message}', '', { closeButton: true, progressBar: true })
});
</script>
EOF
flash_messages << text.html_safe if message
end.join("\n").html_safe
end
Thanks for the feedback. I get the same error still, but this time much more detailed.
Uncaught ReferenceError: toastr is not defined
<anonymous> (index):38
dispatch turbolinks.js:75
notifyApplicationAfterPageLoad turbolinks.js:994
pageLoaded turbolinks.js:948
e turbolinks.js:872
start turbolinks.js:882
start turbolinks.js:1040
<anonymous> application.js:24
<anonymous> application-51d3c38d384dcac9fb08.js:2
Webpack 3
localhost:3000:38:5
<anonymous> (index):38
dispatch turbolinks.js:75
notifyApplicationAfterPageLoad turbolinks.js:994
pageLoaded turbolinks.js:948
e turbolinks.js:872
(Async: EventListener.handleEvent)
start turbolinks.js:882
start turbolinks.js:1040
<anonymous> application.js:24
<anonymous> application-51d3c38d384dcac9fb08.js:2
I have cleared my cache and all the usual things. Is there anything i should be looking out for in those errors?
I load my js in the head tag on my application layout file<%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %>
Thanks
Webpacker doesn't make require available in the browser window, so you have to set that explicitly.
window.toastr = require('toastr')
Working example here for you: https://github.com/excid3/rails_toastr_example