Stimulus not geting values from html
Asked Answered
C

2

7

I'm doing a basic controller and trying to get data from the HTML with the tag value.

The problem is that the data is always empty

<div data-controller="selectable">
  <div class="flex" data-selectable-iconurl="test" data-selectable-iconurl-value="test">
     something here
  </div>
</div>

Notice I did multiple combinations of the value tag ( from different posts) in order to verify if one is working.

Now when I try to access the values in the controller is always empty

// selectable_controller.js

import {Controller} from "@hotwired/stimulus"

export default class extends Controller {
  static values = {iconurl: String }

  connect() {
    console.log(this.iconurlValue)
  }

}

I double-checked the documentation and could not find why the value is not passed to the controller and is always empty

Communism answered 26/9, 2022 at 10:5 Comment(0)
K
10

When Stimulus controller is on the same element as the value, you should be able to retrieve the value:

<div data-controller="selectable" data-selectable-iconurl-value="test">

If your value needs to be set on a child element, then I suggest to just access it the old way :

console.log(this.element.querySelector("div.flex").dataset.selectableIconurlValue)

Though your value may just be treated like a classic HTML element dataset attribute. You lose every Turbo goodness such as observing any change to the value : https://dev.to/borama/stimulus-2-0-value-change-callbacks-what-are-they-good-for-4kho

Not sure why the required location of the value is not precised in the Stimulus Handbook. But the logic is having states on the Stimulus controller, just like what happens in different JS framework, so there is no reason to have the value elsewhere than on the controller anyway.

Kunzite answered 26/9, 2022 at 23:15 Comment(2)
So good, thanks - I had the same problem that I couldn't pass values into my Stimulus controller the official way, so followed your advice but its on the top element so just.. this.element.dataset.selectableInconurlValueLorca
Thank you for this answer! This has been driving me mad for the last hour.Bog
Y
0

Take a look at the target feature, it allows to access an element without a querySelector.

Example:

In the Rails *.erb template:

<!-- In the .erb template: -->
<%= tag.div data: {"controller": "test"}, class: "parent" do %>
  <%= tag.div data: {
    "action": "click->test#action",
    "test-target": "child",
    "my-value": "Hello from a child div!"},
    class: "child" do %>
    Click on me!
  <% end %>
<% end %>

This generates the following HTML markdown:

<div data-controller="test" class="parent">
  <div data-action="click-&gt;test#action" data-test-target="child" data-my-value="Hello from a child div!" class="child">
    Click on me!
</div></div>

Here we establish a connection between the parent div and the test controller. The data-my-value on the child div is the value we want to pass to the controller#action action when it'll be triggered. With the target feature it is as easy as this:

// test_controller.js
import { Controller } from "@hotwired/stimulus"

export default class extends Controller {
  // make the target accessible in this controller:
  static targets = [ "child" ]

  connect() {
    console.log("Connected!");
  };

  action() {
    // access the target element when the action is triggered:
    console.log(this.childTarget);
  };
}

Click on the child div, and you should be able to see the following output in the browser console:

<div class="child" data-action="click->test#action" data-test-target="child" data-my-value="Hello from a child div!">

So what's the child element, and now you can easily access the myValue by doing:

  // ...
  action() {
    let value = this.childTarget.dataset.myValue;
    // => "Hello from a child div!"
  };
Yaupon answered 14/5 at 18:43 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.