Skip to content

Helper functions for morph inhibition in stimulus #801

@brendon

Description

@brendon

I've been converting an app (a newsletter editor that shows changes to the newsletter in realtime via Turbo Streams) to use morphing page updates (for other users) and targeted turbo stream updates for the initiating user.

There are various interfaces in the newsletter such as image panning, dropdowns, colourpickers and a modal interface for the more complex forms. I've found I need to inhibit morphing a lot when these interfaces are active. It's simple for the modals as we never want these to be morphed so we end up with this in initialise() {}:

this.element.addEventListener('turbo:before-morph-element', (event) => {
  if (event.target === this.element) {
    event.preventDefault()
  }
})

Sometimes I just don't want something to revert to its default state (e.g. a dropdown menu should stay open even if its content changes due to a morph:

this.element.addEventListener('turbo:before-morph-attribute', (event) => {
  if (event.target === this.element &&
    this.element.classList.contains('is-active')) {

    event.preventDefault()
  }
})

I prefer to add the listener to the controller element, but sometimes we care about inhibiting on another target inside the controller:

this.element.addEventListener('turbo:before-morph-attribute', (event) => {
  if (event.target === this.buttonTarget &&
    this.buttonTarget.classList.contains('is-loading')) {

    event.preventDefault()
  }
})

I don't know about you, but I can start to see an interface developing here and I wondered if it might be time to build some of this into Stimulus? Of course I can't really see beyond my use cases but I can see perhaps some helper functions like so:

preventElementMorph() // On the controller element
preventElementMorph({target: 'button'}) // On a target element
preventAttributeMorph({classContains: 'is-active'}) // On the controller element
preventAttributeMorph({target: 'button', classContains: 'is-loading'}) // On a target element

I can see some flaws there. Perhaps you'd want to prevent an element morph if a class exists. Perhaps you'd want to be more targeted in what attribute you'd want to prevent the morph of.

I'm hoping this can act as the start of a discussion given morphing and its side effects have now turned succinct Stimulus controllers into a bit of a mess.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions