Stimulus Discourse

Is there a way to dynamically add targets - problem introduced by Phoenix Live View

I have a controller that I use to toggle a set of links (that are littered throughout my page):

import { Controller } from "stimulus"

export default class extends Controller {
  static targets = [
    "edit",
    "insert"
  ]

  connect() {
    this.apply_insert_mode( false )

    for ( var insert of this.inserts ) {
      // Remove the style, so we can control things with classes
      insert.removeAttribute("style")
    }
  }

  toggle() {
    event.preventDefault()

    this.apply_insert_mode( !this.insert_mode );
  }

  apply_insert_mode( insert_mode ) {
    this.insert_mode = insert_mode

    for ( var edit of this.edits ) {
      if ( insert_mode ) {
        edit.classList.add( "hidden" )
      } else {
        edit.classList.remove( "hidden" )
      }
    }

    for ( var insert of this.inserts ) {
      if ( insert_mode ) {
        insert.classList.remove( "hidden" )
      } else {
        insert.classList.add( "hidden" )
      }
    }
  };

  get edits() {
    return this.editTargets
  }

  get inserts() {
    return this.insertTargets
  }
}

Initially all the Edit links are shown. Clicking a “Switch” link will call toggle() and hide all the Edit links and show the Insert links. With traditional server rendered html, this works a treat!

However, I’m playing around with Phoenix Live View. So now, parts of the DOM is dynamically updated. The net effect of this is that some Edit/Insert links are re-rendered. New Edit/Insert links can also be added to the DOM. However, the main problem is that the controller node is never updated. Which means that the targets are constantly changing, but the controller is never re-connected.

I’m assuming that this isn’t what Stimulus is for. But is there something I could do to address this? Can I manually update the list of targets when the DOM changes (using a Phoenix Live View hook)? I’m thinking maybe I could have a global list that I update manually and the controller can access the global list - but that feels like I’m re-writing what Stimulus does.

Any suggestions?

I’m wrong! I had made an (incorrect) assumption that changes to the DOM only matter when a controller (a tag with data-controller) is added/removed. this.editTargets and this.insertTargets return the updated list regardless of whether the DOM has been patched by Live View!

The error was on my part. I had copied some old html that used an inline style (instead of using the hidden class that the above code depends on).