Menu "flashes" in Rails 7 and Turbo

67 views Asked by At

I am trying to build a very simple menu with submenus using Rails 7, Bootstrap 5 and Jquery.

HTML:

   <div>
    <button class="toggle-submenu">Sales</button>
    <div class="submenu">
      <ul>
        <li><a href="/sales/recent">Recent</a></li>
        <li><a href="/sales">All</a></li>
      </ul>
    </div>
  </div>
  <div>
    <button class="toggle-submenu">Products</button>
    <div class="submenu">
      <ul>
        <li><a href="/products">All</a></li>
      </ul>
    </div>
  </div>

CSS:

.submenu {
  height: 0;
  overflow: hidden;
}

.submenu-open {
  height: auto;
}

JS:

$(document).on('click', '.toggle-submenu', function() {
    $(this).parent().find('.submenu').toggleClass('submenu-open');
    $('.submenu').not($(this).parent().find('.submenu')).removeClass('submenu-open');
});

So all this does is when clicking a button, adding the "submenu-open" class to it's closest "submenu" div and removing it from all others.

But what happens is that when clicking on one a link inside the submenu it flashes the other submenu until the server responses (for testing I added a sleep 3 to my controller, and then the "flash" lasted for 3 seconds). See the GIF below:

enter image description here

In the GIF I click on the all link inside products and for a short moment the sales submenu opens.

When disabling turbo the issue disappears. Does anyone have a solution for this?

1

There are 1 answers

2
max On

You're not preventing the default action and not preventing the event from propagating. It would actually be more suprising if the Turbo handler didn't fire and replace the page.

This is something you always have to do when attaching event handlers to elements with default behavior such as links, buttons and forms.

$(document).on('click', '.toggle-submenu', function(event) {
  let active =  $(this).parent().find('.submenu');
  event.preventDefault();
  event.stopPropogation();
  active.toggleClass('submenu-open'); 
  $('.submenu').not(active).removeClass('submenu-open');
});

With jQuery you can also do both by returning false from the event handler.