Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to pass a data value to a stimulus controller upon a load event

I have a Stimulus controller

# app/javascript/controllers/clubs_controller.js
// handles micropost javascripts
import { Controller } from "stimulus"
import Rails from '@rails/ujs';
export default class extends Controller {

  connect() {
    }

    wait_for_clubs(event) {
      event.preventDefault()
      console.log("in wait_for_clubs", event.target)
      const id = event.target.dataset.value
      console.log("id", id)
      }
    }
}

and html code

<div data-controller="clubs">
  <span data-action="load@window->clubs#wait_for_clubs" data-value='<%= @user.id %>'>Waiting for Clubs to be prepared</span>
</div>

with the idea that when the page is loaded, the controller has the id of the user. When I reload the page, I see the following error in the console

TypeError: Cannot read property 'value' of undefined

which is triggered by the var id = event.target.dataset.value; statement.

However if I change the event from load@window to click, then when I click the span, the code works and retrieves the id. How do I fix this?

like image 270
Obromios Avatar asked Sep 20 '20 07:09

Obromios


1 Answers

If you are trying to pass data to a Stimulus controller that exists on the DOM when it loads, the Stimulus docs recommend using the built-in data API.

In your case, that would mean adding a data-clubs-my-value attribute to the DOM element where you assign the data-controller attribute, like so:

<div data-controller="clubs"
     data-clubs-my-value="<%= @user.id %>">
</div>

and then you can get this value from your Stimulus controller by calling this.data.get("myValue")

As to why data-action didn't work...

The Stimulus docs do allow for Global Events so this event is being triggered. But when this happens, the triggering event.target is window, not your <span>, so when you call event.target.dataset, it is looking for the dataset of the window, which does not have your value.

If you want an action in your Stimulus controller to fire upon page load, the best way to handle this is generally by using the connect() method.

like image 62
Ray Avatar answered Oct 21 '22 04:10

Ray