Hello, Stimulus
The best way to learn how Stimulus works is to build a simple controller. This chapter will show you how.
﹟ Prerequisites
To follow along, you’ll need a running copy of the stimulus-starter
project, which is a preconfigured blank slate for exploring Stimulus.
We recommend remixing stimulus-starter
on Glitch so you can work entirely in your browser without installing anything:
Or, if you’d prefer to work from the comfort of your own text editor, you’ll need to clone and set up stimulus-starter
:
$ git clone https://github.com/hotwired/stimulus-starter.git
$ cd stimulus-starter
$ yarn install
$ yarn start
Then visit http://localhost:9000/ in your browser.
(Note that the stimulus-starter
project uses the Yarn package manager for dependency management, so make sure you have that installed first.)
﹟ It All Starts With HTML
Let’s begin with a simple exercise using a text field and a button. When you click the button, we’ll display the value of the text field in the console.
Every Stimulus project starts with HTML. Open public/index.html
and add the following markup just after the opening <body>
tag:
<div>
<input type="text">
<button>Greet</button>
</div>
Reload the page in your browser and you should see the text field and button.
﹟ Controllers Bring HTML to Life
At its core, Stimulus’s purpose is to automatically connect DOM elements to JavaScript objects. Those objects are called controllers.
Let’s create our first controller by extending the framework’s built-in Controller
class. Create a new file named hello_controller.js
in the src/controllers/
folder. Then place the following code inside:
// src/controllers/hello_controller.js
import { Controller } from "@hotwired/stimulus"
export default class extends Controller {
}
﹟ Identifiers Link Controllers With the DOM
Next, we need to tell Stimulus how this controller should be connected to our HTML. We do this by placing an identifier in the data-controller
attribute on our <div>
:
<div data-controller="hello">
<input type="text">
<button>Greet</button>
</div>
Identifiers serve as the link between elements and controllers. In this case, the identifier hello
tells Stimulus to create an instance of the controller class in hello_controller.js
. You can learn more about how automatic controller loading works in the Installation Guide.
﹟ Is This Thing On?
Reload the page in your browser and you’ll see that nothing has changed. How do we know whether our controller is working or not?
One way is to put a log statement in the connect()
method, which Stimulus calls each time a controller is connected to the document.
Implement the connect()
method in hello_controller.js
as follows:
// src/controllers/hello_controller.js
import { Controller } from "@hotwired/stimulus"
export default class extends Controller {
connect() {
console.log("Hello, Stimulus!", this.element)
}
}
Reload the page again and open the developer console. You should see Hello, Stimulus!
followed by a representation of our <div>
.
﹟ Actions Respond to DOM Events
Now let’s see how to change the code so our log message appears when we click the “Greet” button instead.
Start by renaming connect()
to greet()
:
// src/controllers/hello_controller.js
import { Controller } from "@hotwired/stimulus"
export default class extends Controller {
greet() {
console.log("Hello, Stimulus!", this.element)
}
}
We want to call the greet()
method when the button’s click
event is triggered. In Stimulus, controller methods which handle events are called action methods.
To connect our action method to the button’s click
event, open public/index.html
and add a data-action
attribute to the button:
<div data-controller="hello">
<input type="text">
<button data-action="click->hello#greet">Greet</button>
</div>
﹟ Action Descriptors Explained
The
data-action
valueclick->hello#greet
is called an action descriptor. This particular descriptor says:
click
is the event namehello
is the controller identifiergreet
is the name of the method to invoke
Load the page in your browser and open the developer console. You should see the log message appear when you click the “Greet” button.
﹟ Targets Map Important Elements To Controller Properties
We’ll finish the exercise by changing our action to say hello to whatever name we’ve typed in the text field.
In order to do that, first we need a reference to the input element inside our controller. Then we can read the value
property to get its contents.
Stimulus lets us mark important elements as targets so we can easily reference them in the controller through corresponding properties. Open public/index.html
and add a data-hello-target
attribute to the input element:
<div data-controller="hello">
<input data-hello-target="name" type="text">
<button data-action="click->hello#greet">Greet</button>
</div>
Next, we’ll create a property for the target by adding name
to our controller’s list of target definitions. Stimulus will automatically create a this.nameTarget
property which returns the first matching target element. We can use this property to read the element’s value
and build our greeting string.
Let’s try it out. Open hello_controller.js
and update it like so:
// src/controllers/hello_controller.js
import { Controller } from "@hotwired/stimulus"
export default class extends Controller {
static targets = [ "name" ]
greet() {
const element = this.nameTarget
const name = element.value
console.log(`Hello, ${name}!`)
}
}
Then reload the page in your browser and open the developer console. Enter your name in the input field and click the “Greet” button. Hello, world!
﹟ Controllers Simplify Refactoring
We’ve seen that Stimulus controllers are instances of JavaScript classes whose methods can act as event handlers.
That means we have an arsenal of standard refactoring techniques at our disposal. For example, we can clean up our greet()
method by extracting a name
getter:
// src/controllers/hello_controller.js
import { Controller } from "@hotwired/stimulus"
export default class extends Controller {
static targets = [ "name" ]
greet() {
console.log(`Hello, ${this.name}!`)
}
get name() {
return this.nameTarget.value
}
}
﹟ Wrap-Up and Next Steps
Congratulations—you’ve just written your first Stimulus controller!
We’ve covered the framework’s most important concepts: controllers, actions, and targets. In the next chapter, we’ll see how to put those together to build a real-life controller taken right from Basecamp.