AN INTRODUCTION TO STIMULUS.JS
Tags: stimulus, javascript, programming
Published: 2021-04-29 15:05:13



###INTRODUCTION

[Stimulus.js](https://github.com/hotwired/stimulus) 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](https://classic.yarnpkg.com/en/) 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.