Using Values

Let's learn about Stimulus values in this lesson.

Our code is pretty simple so far, but it’s still missing a bit of functionality. We’re not yet changing the text of the button from “Hide” to “Show.” On a more structural level, we don’t have a place in the code that explicitly stores the state of the button. We have to infer the state from the presence or absence of the is-hidden class, which is not a terrible thing to do, but more explicitness is probably useful.

We can do all of these things using another Stimulus concept, values. In Stimulus, values are a bit of syntactic sugar that allows us to use the data attributes to store data that is specifically associated with a controller and gives the controller some methods to manipulate that data directly without dealing with the dataset itself.

To declare a value, we use a similar pattern to what we’ve been using for targets and values. The attribute name itself has multiple parts: data-, the dash-case controller name followed by another hyphen ( - ), and then the name of the attribute.

We want to start with one data HTML attribute for the state of the toggle. This means our attribute name will be data-day-toggle-visible. Note that in this case, the attribute name is in dash-case in the HTML but will be camelCase in the JavaScript.

You typically add the value attributes to the same DOM element that declares the controller, though technically they can be attached to any DOM element inside the controller. Most of the time you want them with the controller declaration so that the data map references are easy to find, which gives us:

<section class="day-body"
  id="day-body-<%= schedule_day.day.by_example("2006-01-02") %>"
  data-controller="day-toggle"
  data-day-toggle-hidden-class="is-hidden"
  data-day-toggle-visible-value="true">

In our case, a “visible” value, where visible is true, means that the target is not hidden.

To use values, we also have to declare them in our controller. Again, sigh, twice. The declaration, values, is another static property, but rather than an array like the other ones we’ve seen, the values property contains an object with the type of each individual value we want to use. At the moment it looks like this:

static values = { visible: Boolean }

The key visible means we’ve declared a visible value in the markup, and the Boolean means we expect the visible value to be a boolean, so Stimulus will automatically convert the string value to a boolean one.

The available types are: Array, Boolean, Number, Object, and String. Boolean and Number are converted from the string using the toString method, while Array and Object are converted using JSON.stringify. If a value isn’t specified the default is an empty object, array, or string, or the number 0, or boolean false.

Declaring a value gives you three properties, similar to what we’ve seen for targets and classes. For the singular (non-array) properties, there’s a property, <valueName>Value, that can be used as a getter and also as a setter, as in visibleValue = true. There’s also a has<valueName>Value which returns true or false depending on whether the attribute is actually present in the DOM. The array properties are the same but plural: <valueName>Values and has<valueName>Values.

Here’s how we might use the value in our controller. We also want to change the button text, so we need the span with the button text to be a target:

<span class="js--button-text" 
      data-day-toggle-target="buttonText">
  Hide
</span>

The controller looks like this:

Get hands-on with 1200+ tech skills courses.