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

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

16 Answers

✔️Accepted Answer

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()

Other Answers:

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

More Issues: