We'll have it wrapped up in time for the 1.0 release. Thanks for your patience!
- Let's build a simple slideshow: A set of slides and buttons for flipping through them
- We'll manage the slideshow's state with DOM data attributes using the Stimulus data API
- Start with the basic HTML:
<div data-controller="slideshow">
<button data-action="slideshow#previous">←</button>
<button data-action="slideshow#next">→</button>
<div data-target="slideshow.slide" class="slide">🐵</div>
<div data-target="slideshow.slide" class="slide">🙈</div>
<div data-target="slideshow.slide" class="slide">🙉</div>
<div data-target="slideshow.slide" class="slide">🙊</div>
</div>
- Add a couple styles to hide all but the current slide:
.slide {
display: none;
}
.slide.slide--current {
display: block;
}
- And here's our initial controller:
// src/controllers/slideshow_controller.js
import { Controller } from "stimulus"
export default class extends Controller {
initialize() {
this.render()
}
next() {
}
previous() {
}
render() {
this.slideElements.forEach((element, index) => {
element.classList.toggle("slide--current", index == this.index)
})
}
get index() {
}
get slideElements() {
return this.targets.findAll("slide")
}
}
- (Describe what
this.render()
does?) - (Describe what
this.targets.findAll()
does? Here or instimulus/handbook/02_hello_stimulus.md
?) - Now let's implement
get index()
:
get index() {
if (this.data.has("index")) {
return parseInt(this.data.get("index"))
} else {
return 0
}
}
-
The data API provides convenient methods for working with scoped data attributes
-
In the DOM, data attributes are scoped using the controller's identifier (
slideshow
in this case)this.data.has("index")
checks if the element has adata-slideshow-index
attributethis.data.get("index")
returns the value of the element'sdata-slideshow-index
attributethis.data.set("index", value)
sets the value of the element'sdata-slideshow-index
attribute
-
Let's add a
set index()
method so we can writeindex
too -
We'll save the value using the data API, and then
render()
to change slides:
set index(value) {
this.data.set("index", value)
this.render()
}
- Now we can implement the
next()
andprevious()
methods - They'll update the value of
index
if there's another slide to navigate to
next() {
if (this.index < this.lastIndex) {
this.index++
}
}
previous() {
if (this.index > 0) {
this.index--
}
}
get lastIndex() {
return this.slideElements.length - 1
}
- We've filled in the missing pieces
- Let's take a look at our final controller:
// src/controllers/slideshow_controller.js
import { Controller } from "stimulus"
export default class extends Controller {
initialize() {
this.render()
}
next() {
if (this.index < this.lastIndex) {
this.index++
}
}
previous() {
if (this.index > 0) {
this.index--
}
}
render() {
this.slideElements.forEach((element, index) => {
element.classList.toggle("slide--current", index == this.index)
})
}
get index() {
if (this.data.has("index")) {
return parseInt(this.data.get("index"))
} else {
return 0
}
}
set index(value) {
this.data.set("index", value)
this.render()
}
get lastIndex() {
return this.slideElements.length - 1
}
get slideElements() {
return this.targets.findAll("slide")
}
}
- Click through the slides and note how
data-slideshow-index
changes in the DOM - Try starting on a different slide by setting an initial index in the HTML:
<div data-controller="slideshow" data-slideshow-index="2">…</div>