DEV Community


Discussion on: Adding Custom JavaScript in Rails 6

duuusha23 profile image
Andrew Aks • Edited

Thanks for the article! I try to call JavaScript 'alert' when clicking the button:

  • JavaScript code is placed in app/javascript/packs/custom.js and contains only this function: function dosmth() { alert(‘hello’); }
  • This file is referenced in app/views/layouts/application.html.erb: <%= javascript_pack_tag ‘custom’ %>
  • Finally, JS code is called on button click in a ERB file: <%= button_tag ‘Do smth’, type: ‘button’, :onclick => “dosmth()” %> When I run the app, I see a compiled script on a page. But when I click the button, I get the error: ReferenceError: Can’t find variable: dosmth. Could you please help if you have any ideas? inspect
morinoko profile image
Felice Forby Author • Edited

Well, I did some digging... Since these are webpack modules, I guess you have to do a little more work to make the function available if you're simply declaring it in pack/custom.js. First, you need to export function by adding an export at the end of the file:

// javascript/packs/custom.js

function dosmth() { 

export default dosmth;

Then, in the main application.js, you have to import it and make it available to the window. You can do that by adding this to the bottom of application.js

// javascript/packs/application.js

// require statements, etc....

import dosmth from './custom'
window.dosmth = dosmth

Then it should work! I think there's a way to export and import all functions in a file too... I'm not very familiar with how webpack works yet, but I'll try to update this post with some more info soon.

Instead of exporting/importing, another way is to add the onClick function with an event listener instead. First, give your button and id or something like that and remove the onclick:

<%= button_tag 'Do smth', id: 'button-click', type: 'button' %> 

Then in the custom.js file, add an event listener:

// javascript/packs/custom.js

function dosmth() { 

document.addEventListener('turbolinks:load', () => {  
  const clickButton = document.getElementById("button-click");  

  clickButton.addEventListener("click", dosmth); 

You do need to make sure you wrap the event listener (and other JS) inside the document.addEventListener('turbolinks:load', () => {}. That's Rails' way of making sure the page and turbolinks is loaded before any of the javascript gets executed!

I hope that helps!! I learned a bit trying to figure this out too!

duuusha23 profile image
Andrew Aks

Ooh, great thanks, Felice!

johnviviano profile image
John Viviano

Thanks for this article. It was helpful. Changing the declaration of your JavaScript function may simplify things a bit:

// in your html
<a href="#" onclick="dosmth()">dosmth</a>

// javascript/packs/custom.js
window.dosmth = function() {

// I don't think you need the export default dosmth;
// export default dosmth;

// In your javascript/packs/application.js I don't think you need the corresponding declarations:

// import dosmth from './custom'
// window.dosmth = dosmth