Dynamically attaching elements with data-action


#1

Hello,

First of all, thanks for this great framework.

For some reason when I try to dynamically attach elements coming from a remote source to the DOM, the data-action attributes that each one of them defines doesn’t seem to work. Specifically, the redirect function inside the controller never gets called.

<% @collection.compact.each do |resource| %>
  <li class="result" data-action="click->autocomplete#redirect">
    <%= resource.name %>
  </li>
<% end %>
<div class="autocomplete" data-controller="autocomplete">
  <!-- ... -->

  <ul class="results hide" data-target="autocomplete.results"></ul>

  <!-- ... -->
</div>
import { Controller } from "stimulus"

export default class extends Controller {
  // ...

  fetch() {
    if (this.queryTarget.value.length > 0) {
      fetch(`search/games?query=${this.queryTarget.value}`)
        .then((response) => response.text())
        .then(this.handleResults.bind(this))
    } else {
      this.handleEmptyQuery()
    }
  }

  handleResults(html) {
    this.resultsTarget.innerHTML = html
    this.resultsTarget.classList.remove('hide')
  }

  handleEmptyQuery() {
    this.resultsTarget.innerHTML = ''
    this.resultsTarget.classList.add('hide')
  }

  redirect(arg) {
    // NEVER GETS CALLED!!!
    // NEVER GETS CALLED!!!
    // NEVER GETS CALLED!!!
    console.log('>>>', arg)
  }
}

What could I be missing?

Thanks.


#2

Could this have something to do with the way that you are connecting the newly inserted elements into your list?

Assuming your fetch is retrieving results and inserting them into the page, the first thing that came to mind to me is that the newly inserted elements need to be attached to your event/click handler.

Thinking maybe it’s could be a situation where you need to use connect() vs. initialize().

https://stimulusjs.org/handbook/managing-state#lifecycle-callbacks-explained


#3

Your HTML looks like it should work. I made a low-fi copy of your controller and it works as expected too: https://jsfiddle.net/javan/x4p8n7mb/.

Maybe try console.log()ing the HTML you’re inserting and make sure it’s formatted like you expect.


#4

@kylekeesling Thanks! I was mislead by thinking something similar (which brought me here in the first place), but as it turns out Stimulus does recognise elements being dynamically attached to the DOM by default.

@javan Thanks! Your example pointed me to what I was doing wrong, which had nothing to do with Stimulus dynamically attaching elements to the DOM, since as you shown, the framework handles these cases very smoothly.