Materialize: [1.0.0.alpha1] Side nav doesn't work with turbolinks 5

Created on 23 Nov 2017  Â·  14Comments  Â·  Source: Dogfalo/materialize

I discovered this issue when I was trying to upgrade to materialize 1.0.0.alpha1, and I managed to create a sample app showing the issue.

You can find the sample app right here

To reproduce the error with the sample app do the following:

  1. Download the code and run rails s
  2. Click the menu icon on the left of the navbar to open the sidenav
  3. Click on any of the links on the sidenav
  4. Try to open the sidenav again by clicking the same icon from before
  5. The sidenav won't open again because the page now refreshes each time you click the icon

If you comment out the //= require turbolinks from the application.js file, it works as expected.

Expected behavior
Side nav opens every time I click the trigger button

Actual behavior
Side nav only works the first time you open it

Most helpful comment

seem like instance still alive when turbolinks:load page.
it works if we destroy the existing instance using turbolinks:before-visit.

$(document).on 'ready turbolinks:load', ->
  elem = document.querySelector('#slide-out');
  instance = new M.Sidenav(elem, {});

$(document).on 'ready turbolinks:before-visit', ->
  elem = document.querySelector('#slide-out');
  instance = M.Sidenav.getInstance(elem);
  instance.destroy()

All 14 comments

Most likely this is the issue you are facing:
https://stackoverflow.com/questions/18769109/rails-4-turbo-link-prevents-jquery-scripts-from-working

On Wed, Nov 22, 2017 at 4:50 PM, Guilherme Pejon notifications@github.com
wrote:

I discovered this issue when I was trying to upgrade to materialize
1.0.0.alpha1, and I managed to create a sample app showing the issue.

You can find the sample app right here
https://github.com/guilpejon/materialize_turbolinks_issue

To reproduce the error with the sample app do the following:

  1. Download the code and run rails s
  2. Click the menu icon on the left of the navbar to open the sidenav
  3. Click on any of the links on the sidenav
  4. Try to open the sidenav again by clicking the same icon from before
  5. The sidenav won't open again because the page now refreshes each
    time you click the icon

If you comment out the //= require turbolinks from the application.js
file, it works as expected.

Expected behavior
Side nav opens every time I click the trigger button

Actual behavior
Side nav only works the first time you open it

—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
https://github.com/Dogfalo/materialize/issues/5396, or mute the thread
https://github.com/notifications/unsubscribe-auth/ACpaxyI3tCO7KaR3iArYxZYoQEYUTMvKks5s5ME7gaJpZM4QoKhe
.

--
Doggy sends his greetings from Mars.

I think it's probably related to the fact that the javascript is being loaded just once, but I had the same setup with the older version of materialize and the sidenav worked just fine alongside Turbolinks (it's even in production), so that's why I think it could be related to an issue with the newer version.

Why does your page refresh when you click the icon? That shouldn't be happening

I'm using the materialize-sass gem to add Materialize to my project, and here is the code to initialize the sidenav with Turbolinks:

$(document).on 'turbolinks:load', ->
  $('.sidenav').sidenav()

My guess is that after I open the sidenav and click in one of its links to close it, I somehow lose the link between the sidenav and my anchor tag, so if I click the menu icon to open it again, the page tries to render the href='#!' of my icon and refreshes the page.

try adding prevent default to the <a>

It stops the page refreshing, but it doesn't open the sidenav again.

you should probably init on page:change but either way I don't think this is a bug in Materialize.

seem like instance still alive when turbolinks:load page.
it works if we destroy the existing instance using turbolinks:before-visit.

$(document).on 'ready turbolinks:load', ->
  elem = document.querySelector('#slide-out');
  instance = new M.Sidenav(elem, {});

$(document).on 'ready turbolinks:before-visit', ->
  elem = document.querySelector('#slide-out');
  instance = M.Sidenav.getInstance(elem);
  instance.destroy()

Thank you @mkhairi, that works!

I'm getting same issue.
thank you @mkhairi .
I wrote ES6 version (not using jQuery)

  document.addEventListener('turbolinks:load', function() {
    elem = document.querySelector('#slide-out');
    instance = new M.Sidenav(elem, {});
  });
  document.addEventListener('turbolinks:before-visit', function() {
    elem = document.querySelector('#slide-out');
    instance = M.Sidenav.getInstance(elem);
    instance.destroy();
  });

prevent "TypeError: instance is undefined" error when new page loaded.

  document.addEventListener('turbolinks:load', function() {
    elem = document.querySelector('#slide-out');
    instance = new M.Sidenav(elem, {});
  });
  document.addEventListener('turbolinks:before-visit', function() {
    elem = document.querySelector('#slide-out');
    instance = M.Sidenav.getInstance(elem);
    if (instance){
      instance.destroy();
    }
  });

Note that turbolinks:before-visit is only emitted for navigation events, and will not be emitted if a user clicks the back button. 'turbolinks:before-render is emitted right before the body is swapped.

// https://github.com/Dogfalo/materialize/issues/5396
document.addEventListener('turbolinks:before-render', () => {
  const elem = document.querySelector('#slide-out');
  const instance = M.Sidenav.getInstance(elem);
  if (instance) {
    instance.destroy();
  }
});

the correct event of turbolinks to fixing this is turbolinks:before-cache

seem like instance still alive when turbolinks:load page.
it works if we destroy the existing instance using turbolinks:before-visit.

$(document).on 'ready turbolinks:load', ->
  elem = document.querySelector('#slide-out');
  instance = new M.Sidenav(elem, {});

$(document).on 'ready turbolinks:before-visit', ->
  elem = document.querySelector('#slide-out');
  instance = M.Sidenav.getInstance(elem);
  instance.destroy()

Hi, I'm trying to test MaterializeCSS on my rails app with M.AutoInit(), and running into the same issue (sidebar working on first load, but not after clicking on a link or using the browser's back button). Is that possible? In which file should I add the (edited) code you provided? Thanks!

Thanks @mkhairi, @elmoaaron from 2021 :) . Had the same problem, banged my head for hours with this one until I found this.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

ReiiYuki picture ReiiYuki  Â·  3Comments

samybob1 picture samybob1  Â·  3Comments

ericlormul picture ericlormul  Â·  3Comments

acierpinski picture acierpinski  Â·  3Comments

cope picture cope  Â·  3Comments