Turbolinks + dropdown issues

It’s not fully related to Stimulus but there are so much smart folks in here i just couldn’t resist. Anyway, i’m working on this as on a Stimulus controller.


I have a pretty basic dropdown menu controller with show/hide actions. My turbolinks-based site acts weird when it comes to caching the dropdown. Example scenario:

I’m on a page A, i open the dropdown, click on one of the links in the dropdown, dropdown closes itself, user gets redirected to the clicked page B, user then clicks link “Back to page A” which brings him back to page A and…the dropdown is visible there and closes itself after a second. You can see that on your own on this website: https://prismo.news - just do what i recorded below:

So, what i assume is happening here is when i click the Comments link, Turbolinks caches the dropdown in the opened state so when i’m getting back to the start, Turbolinks loads cached opened dropdown and shows it to me for a sec. Does it sound possible?

I tried setting up my dropdown controller as follows but it doesn’t seem to resolve my issue:

  connect() {
    this._popper = new Popper(this.toggleTarget, this.dropdownTarget, {
      placement: this.placement,
      eventsEnabled: false
    })

    document.addEventListener('turbolinks:before-cache', function () {
      // dropdown closing logic here
    })
  }

Am i doing any wrong assumptions in here? Is the code above even a proper way of handling turbolinks events?

If that’s needed, here is my controller’s code:

https://gitlab.com/mbajur/prismo/blob/master/app/javascript/packs/controllers/dropdown_controller.js

Thanks in advance for any clues!

ps. after this gets resolved, i’m gonna definitely think about releasing this as a stimulus-popper component.

I’m sorry, this topic can be closed now. The issue was super lame - i’ve been using

function () {}

instead of

() => {}

so the callback has been loosing the scope and this.opened was not properly called. Sorry for confusion.

A dumb question but what is the difference between the two.
My understanding is that () => {} is a short hand, though i never used it.

function () {}
() => {}

Not a dumb question! :slight_smile: The arrow function doesn’t have its own bindings, which means this has a different meaning inside the function depending on what syntax you use.

Arrow functions are really handy in JavaScript classes, like Stimulus controllers, when you want to reference the current object instance inside callbacks.

Using the code from the original post as an example:

connect() {
  document.addEventListener('turbolinks:before-cache', function () {
    console.log(this) // Outputs the document object
  })
}
connect() {
  document.addEventListener('turbolinks:before-cache', () => {
    console.log(this) // Outputs the Stimulus controller instance
  })
}
5 Likes