Stimulus reference
What is Stimulus?
Stimulus is a lightweight JavaScript framework for enhancing static or server-rendered HTML – the “HTML you already have” – by connecting your HTML elements with JS objects using simple data-
attributes.
Just as a class
attribute connects HTML to CSS, Stimulus’s data-
attributes connects HTML to JavaScript.
It’s not intended to power a single-page application in the way that frameworks like React, Angular or Vue are. Stimulus is used mostly in conjuction with server-rendered HTML templates.
Stimulus vs mainstream JS frameworks
Manipulates existing HTML
Stimulus focuses on manipulating existing HTML that comes from the server. This contrasts with most frameworks like React or Angular that typically fetch JSON and use that to dynamically create the DOM.
State is managed in HTML instead of JS
Stimulus stores state in the HTML instead of JS objects.
The main concepts
Stimulus revolves around three main concepts:
- Controllers – the JavaScript objects that are connected to HTML and used to manipulate it.
- Actions – connect DOM events to controller methods using
data-action
attributes. - Targets – locates HTML elements within a controller.
Here’s an example HTML that uses Stimulus:
<div data-controller="clipboard">
PIN: <input data-clipboard-target="source" type="text" value="1234" readonly>
<button data-action="clipboard#copy">Copy to Clipboard</button>
</div>
Lifecycle methods
Method | Description |
initialize() | Invoked once when the controller is first instantiated. |
connect() | Invoked anytime the controller is connected to the DOM. |
disconnected() | Invoked anytime the controller is disconnected from the DOM. |
Recipes
Connect HTML to controller
Create controller:
// src/controllers/hello_controller.js
import { Controller } from "@hotwired/stimulus"
// Connects to data-controller="hello-converter"
export default class extends Controller {
connect() {
console.log('Hello Stimulus', this.element)
}
}
Link HTML to controller:
<div data-controller="hello">
<input type="text">
<button>Greet</button>
</div>
Invoke action on DOM event.
<div data-controller="hello">
<input type="text">
<button data-action="click->hello#greet">Greet</button>
</div>
Clicking on the button will invoke the method greet
from the controller in hello_controller.js
.
Target DOM elements within a controller
Add the target annotation to HTML element:
<div data-controller="hello">
<input data-hello-target="name" type="text">
<button data-action="click->hello#greet">Greet</button>
</div>
Target the HTML element:
// 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}!`)
}
}
Read initial state from the DOM
Add data-<controller>-value
attribute:
<div data-controller="slideshow" data-slideshow-index-value="1">
Add a static values
definition to the controller:
export default class extends Controller {
static values = { index: Number }
initialize() {
console.log(this.indexValue)
console.log(typeof this.indexValue)
}
// …
}
this.indexValue
will return "1"
.
Invoke callback when value changes
Given this HTML:
<div data-controller="slideshow" data-slideshow-index-value="1">
<button data-action="slideshow#previous"> ← </button>
<button data-action="slideshow#next"> → </button>
<div data-slideshow-target="slide">🐵</div>
<div data-slideshow-target="slide">🙈</div>
<div data-slideshow-target="slide">🙉</div>
<div data-slideshow-target="slide">🙊</div>
</div>
and this controller:
import { Controller } from "@hotwired/stimulus"
export default class extends Controller {
static targets = [ "slide" ]
static values = { index: Number }
next() {
this.indexValue++
}
previous() {
this.indexValue--
}
indexValueChanged() {
this.showCurrentSlide()
}
showCurrentSlide() {
this.slideTargets.forEach((element, index) => {
element.hidden = index != this.indexValue
})
}
}
Everytime the user clicks the next or previous buttons, the indexValue
is changed and the indexValueChanged
callback is invoked.
Sources
Thanks for your comment 🙏. Once it's approved, it will appear here.
Leave a comment