2023-05-18 - Stimulus JS
main topics
During this lecture I noticed a knowledge gap about webpack. Solved this by watching this origamid lecture
Stimulus
A modest JavaScript framework for the HTML you already have.
- Organize your JavaScript code into dedicated
controller.js
files.- Don't write
querySelector
oreventListener
ever again!- Bind JavaScript behavior to HTML elements using
data-attributes
instead.
So, the "3 steps JS" thing that I memorized can now be simplified.
The "3 steps JS":
- select some elements
- define a function (behavior)
- define which event, happening in wich element, should trigger which function (sometimes changing other elements)
With Stimulus our JavaScript code will be focused on the behavior. The elements to be selected and the events we want to listen are explicitly mentioned in the HTML, specifically in the elements' data-attributes
.
While reading The Origin of Stimulus I noticed that "the focus of Stimulus is on manipulating, not creating, DOM elements."
Unlike other front-end frameworks, Stimulus is designed to enhance static or server-rendered HTML—the “HTML you already have”—by connecting JavaScript objects to elements on the page using simple annotations.
(...) Stimulus’s use of data attributes helps separate content from behavior in the same way CSS separates content from presentation.
Key Concepts
- Data Controllers
- Data Actions
- Data Targets
mnemonic: CAT 😺
Controllers
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 src/controllers/hello_controller.js
:
// src/controllers/hello_controller.js
import { Controller } from "@hotwired/stimulus"
export default class extends Controller {}
In order to connect to this 👆 controller, we need to go to our HTML and mark an element there as data-controller
. Like this:
<div data-controller="hello">
<input type="text">
<button>Greet</button>
</div>
NOTE: inside the Controller class, the this.element
has the element where the data-controller
attribute is defined.
NOTE 2: you can do this this.element.querySelector(cssSelector)
.
Actions
An action assign a behavior to an element. Here's an example:
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
value click->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
Remember: inside the Controller class, the this.element
has the element where the data-controller
attribute is defined.
Targets
A Target is an element on which we want to act.
In the HTML it's like this:
<div data-controller="hello">
// here 👇
<input data-hello-target="name" type="text">
<button data-action="click->hello#greet">Greet</button>
</div>
And in the *_controller.js
we can grab it like this:
import { Controller } from "@hotwired/stimulus"
export default class extends Controller {
// the target name goes as an element of `targets`
static targets = [ "name" ]
greet() {
// and it's accessible by `this.${targetName}Target`
const element = this.nameTarget
const name = element.value
console.log(`Hello, ${name}!`)
}
}
Installation
Installation guide (assumes use of webpack).
npm install @hotwired/stimulus
npm install @hotwired/stimulus-webpack-helpers
Put this in index.js
(or whichever file is linked in your html):
import { Application } from "@hotwired/stimulus"
import { definitionsFromContext } from "@hotwired/stimulus-webpack-helpers"
window.Stimulus = Application.start()
const context = require.context("./controllers", true, /\.js$/)
Stimulus.load(definitionsFromContext(context))
Now you can create #Controllers.