DEV Community

Allan
Allan

Posted on • Updated on

AN INTRODUCTION TO STIMULUS.JS

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>
Enter fullscreen mode Exit fullscreen mode

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')
    }
}
Enter fullscreen mode Exit fullscreen mode

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

Enter fullscreen mode Exit fullscreen mode

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>
Enter fullscreen mode Exit fullscreen mode

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 {

}
Enter fullscreen mode Exit fullscreen mode

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>
Enter fullscreen mode Exit fullscreen mode

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>
Enter fullscreen mode Exit fullscreen mode

And in the controller, add:

import { Controller } from "stimulus"

export default class extends Controller {

  initialize() {
    this.index = 0
  }

  next() {
    this.index++
  }

  previous() {
    this.index--
  }
}
Enter fullscreen mode Exit fullscreen mode

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>

Enter fullscreen mode Exit fullscreen mode

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>
Enter fullscreen mode Exit fullscreen mode

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--
  }
}
Enter fullscreen mode Exit fullscreen mode

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
    })
  }
Enter fullscreen mode Exit fullscreen mode

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
    })
  }
} 
Enter fullscreen mode Exit fullscreen mode

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)