1

In my view I'm trying to call a JavaScript function which I've placed in application.js:

/* Set the width of the side navigation to 250px */
function openNav() {
  document.getElementById("mySidenav").style.width = "250px";
}

/* Set the width of the side navigation to 0 */
function closeNav() {
  document.getElementById("mySidenav").style.width = "0";
}

This is my HTML:

<div id="mySidenav" class="sidenav">
  <a href="javascript:void(0)" class="closebtn" onclick="closeNav()">&times;</a>
  <a href="#">About</a>
  <a href="#">Services</a>
  <a href="#">Clients</a>
  <a href="#">Contact</a>
</div>

<span style="font-size:30px;cursor:pointer" onclick="openNav()">&#9776; open</span>

If I put this in my view within <script></script> tags, then it works. My application.js works and it's being compiled but for some reason it only works if the JavaScript is in the actual view of the html.erb file. But if it's in application.js in my pack folder, although it builds the JavaScript file, it returns this error in the console:

(index):23 Uncaught ReferenceError: openNav is not defined
    at HTMLSpanElement.onclick ((index):23)

How can I get this to work in my pack/application.js file rather than having it in the theme in a <script> tag?

the Tin Man
  • 158,662
  • 42
  • 215
  • 303
soniccool
  • 5,790
  • 22
  • 60
  • 98
  • Please don't edit your question to tell us you found a solution. Questions are specifically for the question, just as answers are only for answers. SO isn't a message list or a forum, it's like an online text book, where you just created a new article. It's more formal than either of the other two types of sites. The [tour] and "[ask]" and its linked pages discuss this. – the Tin Man May 06 '20 at 03:54

2 Answers2

4

"Rails 5/6: How to include JS functions with webpacker?" worked:

window.closeNav = function() {
  document.getElementById("mySidenav").style.width = "0";
}

window.openNav = function() {
  document.getElementById("mySidenav").style.width = "250px";
}

Can anyone explain why in Rails 6?

the Tin Man
  • 158,662
  • 42
  • 215
  • 303
soniccool
  • 5,790
  • 22
  • 60
  • 98
1

It is unclear why the function openNav() does not work in Rails 6. I would suspect that it has to do with the changes from Sprockets to Webpacker. I did find a solution that may be more conventional than adding the methods to the "window" object. Adding methods or properties directly to the "window" object could inadvertently overwrite defaults. I took guidance from the RailsGuides.

https://edgeguides.rubyonrails.org/working_with_javascript_in_rails.html

I added an "id" to the Open and Close elements and removed their "onclick" properties. Adding the ids allowed me to target them in the side_nav.js file to add a "click" event listeners.

Index.html.erb

<div id="mySidenav" class="sidenav">
  <a href="#" class="closebtn" id="close-nav >&times;</a>
  <a href="#">About</a>
  <a href="#">Services</a>
  <a href="#">Clients</a>
  <a href="#">Contact</a>
</div>

<span id="open-nav>Open</span>

<%= javascript_pack_tag 'side_nav' %>

I am using Turbolinks, and so I wait to add the event listeners until after the Turbolinks loads to make sure that the DOM is finished rendering. This will make sure the "id" are available to be targeted. If you are not using Turbolinks you may be able to change it out for "DOMContentLoaded".

javascript\packs\side_nav.js

window.addEventListener("turbolinks:load", () => {
  // Open
  document.getElementById('open-nav').addEventListener("click", e => {
    e.preventDefault();
    document.getElementById("mySidenav").style.width = "250px";
  });

  // Close
  document.getElementById('close-nav').addEventListener("click", e => {
    e.preventDefault();
    document.getElementById("mySidenav").style.width = "0";
  });
});