Was updating my site today and noticed that my navbar is still using vanilla javascript to handle the toggling of the responsive menu at mobile size. This will not do!
Here's how I converted it to Alpine JS.
This was the script that was responsible for the behavior before:
1document.addEventListener('DOMContentLoaded', function () {2 let toggleBtn = document.getElementsByClassName('menu-toggle')[0]3 let menu = document.getElementsByClassName('navbar-menu')[0]45 toggleBtn.addEventListener('click', () => {6 toggleBtn.classList.toggle('is-active')7 menu.classList.toggle('hide')8 })9})
1document.addEventListener('DOMContentLoaded', function () {2 let toggleBtn = document.getElementsByClassName('menu-toggle')[0]3 let menu = document.getElementsByClassName('navbar-menu')[0]45 toggleBtn.addEventListener('click', () => {6 toggleBtn.classList.toggle('is-active')7 menu.classList.toggle('hide')8 })9})
Breaking that down, we're basically just attaching a "click" listener to the hamburger button (which has a class menu-toggle
) which toggles some classes on the menu itself. Simple, but we had to write this big chunk of javascript to accomplish it. We can do better.
With Alpine we just need to add a few sprinkles to our template and we can get rid of all that javascript.
First, initialize a new component by setting some data on the parent tag. This will track the navbar's open/closed state.
1<div class="navbar" x-data="{ open: false }"></div>
1<div class="navbar" x-data="{ open: false }"></div>
Next, we need the button to change the open
variable we just defined.
1<button class="menu-toggle" @click.prevent="open = !open">...</button>
1<button class="menu-toggle" @click.prevent="open = !open">...</button>
Finally, we just need the navbar to show and hide based on the state of our open
data.
1<ul class="navbar-menu" :class="{ 'hide': !open }"></ul>
1<ul class="navbar-menu" :class="{ 'hide': !open }"></ul>
You could also use
x-show
to hide the element, I already had this "hide" class which has some CSS transitions attached to it, so I applied the class whenopen == false
instead.
There you have it!
Don't know about you, but I'll take three properties in the DOM instead of that chunk of custom javascript any day.