Reputation: 6058
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()">×</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()">☰ 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?
Upvotes: 1
Views: 1568
Reputation: 31
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 >×</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";
});
});
Upvotes: 1
Reputation: 6058
"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?
Upvotes: 4