INTRODUCTION
Stimulus.js is a modest JavaScript framework for the HTML you already have by connecting JavaScript objects(controllers) to the HTML on the page in an organized way.
Unlike other JavaScript frameworks, it doesn't take over your entire front-end's application. The Basecamp team created it to simplify the problem of heavy frontend-driven architecture that's currently in vogue.
This article will introduce you to stimulus.js by creating a slideshow and how it can help structure an application's front-end codebase.
PREREQUISITE
For this tutorial, you will need:
- A basic understanding of HTML.
- Yarn installed on your P.C
HOW STIMULUS.JS DIFFERS FROM MODERN JAVASCRIPT FRAMEWORKS
Stimulus.js differs from modern JavaScript frameworks that are available today. It doesn't render templates like these modern JavaScript frameworks that rely on turning JSON into DOM elements via a template language. It relies on the DOM to hold the state. It also connects actions and events on the front-end of an application to controllers on the backend.
CORE CONCEPTS
Stimulus.js has three(3) main concepts. These are controllers, actions, and targets. Here’s an example of code you’ll write to copy text from an input field to the clipboard:
<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>
And the accompanying JavaScript looks like this.
#clipboard_controller.js
import {Controller} from "stimulus"
export default class extends Controller{
static targets = ['source']
copy(){
this.sourceTarget.select()
document.execCommand('copy')
}
}
Controllers
Controllers refer to instances of JavaScript classes that you define in your application. The data-controller
attribute connects the HTML to the JavaScript.
Actions
Think of actions as a way of handling DOM events in your controller. In the clipboard markup, the data attribute data-action="clipboard#copy"
copies the text when we click on the button in the HTML and runs the action copy
in the controller.
Targets
Targets let you define essential elements that will be available to your controller. The data-clipboard-target=" source"
sets up a target with the name source
in the controller, and we can access this by using this.sourceTarget
.
GETTING STARTED
To get started, you need to clone and set up stimulus-starter
. You can do this by using the commands:
$ git clone https://github.com/hotwired/stimulus-starter.git
$ cd stimulus-starter
$ yarn install
$ yarn start
Then visit http://localhost:9000/
in your browser.
CREATING A SLIDESHOW WITH STIMULUS.JS
In this section, I will demonstrate how to create a slideshow using stimulus.js.
CREATING A CONTROLLER
Open the index file in the public directory and update it with this code.
<div data-controller="slideshow">
</div>
In the stimulus-starter
, there is a controller folder so let's create a file slideshow_controller.js
and add this:
import { Controller } from "stimulus"
export default class extends Controller {
}
Let's break down what's going on in the code snippets above.
The data-controller
attribute connects our controller to the DOM with the identifier slideshow.
CONNECTING THE ACTION
Now, let's add a button inside the <div>
to connect the action method to the button's click
event. We can do this by adding a data-action
attribute to the button.
<button data-action="click->slideshow#previous" class="btn"> ← </button>
<button data-action="click->slideshow#next" class="btn"> → </button>
We now have
<div data-controller="slideshow">
<button data-action="click->slideshow#previous" class="btn"> ← </button>
<button data-action="click->slideshow#next" class="btn"> → </button>
</div>
And in the controller, add:
import { Controller } from "stimulus"
export default class extends Controller {
initialize() {
this.index = 0
}
next() {
this.index++
}
previous() {
this.index--
}
}
We can look at the code snippet above and understand what is going on.
The data-action
value click->slideshow#previous
and click->slideshow#next
are called action descriptors. The descriptor says that:
-
click
is the name of the event -
slideshow
is the controller identifier -
previous
,next
are the names of the method
The initialize
method shows the first slide. The next()
and previous()
method in the controller advance and goes back to the current slide when we click on the button(for now, the button doesn't do anything when we click on it).
USING TARGETS
Add the following in the <div>
.
<div data-slideshow-target="slide">slide 1</div>
<div data-slideshow-target="slide">slide 2</div>
<div data-slideshow-target="slide">slide 3</div>
We have this now.
<div data-controller="slideshow">
<button data-action="click->slideshow#previous" class="btn"> ← </button>
<button data-action="click->slideshow#next" class="btn"> → </button>
<div data-slideshow-target="slide">slide 1</div>
<div data-slideshow-target="slide">slide 2</div>
<div data-slideshow-target="slide">slide 3</div>
</div>
In the code above, we created a target by adding data-slideshow-target
with the value slide to the div
element.
Next, let's create a property for the target by adding slide to the target definition in the controller. Stimulus.js automatically creates a this.slideTarget
property to get the first element.
import { Controller } from "stimulus"
export default class extends Controller {
static targets = [ "slide" ]
initialize() {
this.index = 0
}
next() {
this.index++
}
previous() {
this.index--
}
}
Now let's add a method showCurrentSlide()
which will loop through each slide target.
showCurrentSlide() {
this.slideTargets.forEach((element, index) => {
element.hidden = index != this.index
})
}
What this does is it will loop through each slide target and toggles the hidden
attribute if its index matches.
Update the slideshow_controller.js
like this.
import { Controller } from "stimulus"
export default class extends Controller {
static targets = [ "slide" ]
initialize() {
this.index = 0
this.showCurrentSlide()
}
next() {
this.index++
this.showCurrentSlide()
}
previous() {
this.index--
this.showCurrentSlide()
}
showCurrentSlide() {
this.slideTargets.forEach((element, index) => {
element.hidden = index != this.index
})
}
}
You can reload the page in the browser and confirm that the previous or next button goes back or advances to the next slide.
CONCLUSION
In this tutorial, we learn't what stimulus.js is, the core concepts, and demonstrated how to create a slideshow.
Top comments (0)