Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Closed
guilpejon opened this issue Nov 23, 2017 · 16 comments
Closed

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

guilpejon opened this issue Nov 23, 2017 · 16 comments

Comments

@guilpejon
Copy link

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

@Dogfalo
Copy link
Owner

Dogfalo commented Nov 23, 2017 via email

@guilpejon
Copy link
Author

guilpejon commented Nov 23, 2017

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.

@Dogfalo
Copy link
Owner

Dogfalo commented Nov 23, 2017

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

@guilpejon
Copy link
Author

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.

@Dogfalo
Copy link
Owner

Dogfalo commented Nov 23, 2017

try adding prevent default to the <a>

@guilpejon
Copy link
Author

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

@Dogfalo
Copy link
Owner

Dogfalo commented Nov 23, 2017

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

@Dogfalo Dogfalo closed this as completed Nov 23, 2017
@mkhairi
Copy link

mkhairi commented Nov 23, 2017

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

@guilpejon
Copy link
Author

Thank you @mkhairi, that works!

@garin
Copy link

garin commented Feb 20, 2018

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

@tatethurston
Copy link

tatethurston commented Dec 3, 2018

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

@elmoaaron
Copy link

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

@Dijkie85
Copy link

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!

@Goku-San
Copy link

Goku-San commented Jan 22, 2021

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

@luchillo17
Copy link

luchillo17 commented Jun 14, 2021

Thanks, @mkhairi, @elmoaaron you guys saved my bacon there, here's a link to the docs related to turbolinks:before-cache if anyone else needs more explanation on it:
https://github.com/turbolinks/turbolinks#understanding-caching

@elissonmichael
Copy link

I have found a solution for this using Rails 7 & Stimulus:

  initialize() {
    M.AutoInit();
  }
  
  disconnect() {
    M.Sidenav._sidenavs = [];
  }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

10 participants