An Introduction To Stimulus.js

What is it & when is it useful?

Before I start

What we'll cover

  • Where does Stimulus Come From?
  • What does it look like?
  • When is it useful?
  • How can we set it up in Rails!

The outcome should be you'll confident enough to give Stimulus a try & know about where it's useful.

Where does Stimulus Come From?

When Ruby On Rails first started, our options were limited.

Where does Stimulus Come From?

Then we ended up with libraries which favoured rendering on the client side.

Where does Stimulus Come From?

HTML is faster then React

Where does Stimulus Come From?

  • It was made Javan Makhmali (He works at Basecamp)
  • First launched released in January 2018
  • Current version is v1.1.1

Where does Stimulus Come From?

$ rails webpacker
Available Webpacker tasks are:
webpacker:info                Provides information on Webpacker's environment
webpacker:install:react       Installs and setup example React component
webpacker:install:vue         Installs and setup example Vue component
webpacker:install:angular     Installs and setup example Angular component
webpacker:install:elm         Installs and setup example Elm component
webpacker:install:svelte      Installs and setup example Svelte component
webpacker:install:stimulus    Installs and setup example Stimulus componentwebpacker:install:erb         Installs Erb loader with an example
webpacker:install:coffee      Installs CoffeeScript loader with an example
webpacker:install:typescript  Installs Typescript loader with an example

What does it look like?

<!-- index.html -->
<div data-controller="counter">
  <span data-target="counter.output"></span>
  <button data-action="click->counter#addOne">
    Add One
  </button>
</div>
0
// counter_controller.js
import { Controller } from "stimulus"

export default class extends Controller {
  static targets = [ "output" ]
  
  initialize(){
    this.clickCount = 0
  }
  
  connect(){
    this._updateOutput();
  }

  addOne() {
    this.clickCount++;
    this._updateOutput();
  }
  
  _updateOutput() {
    this.outputTarget.innerText = `You've clicked ${this.clickCount} times`
  }
};

What does it look like?

<!-- index.html -->
<div data-controller="counter">  <span data-target="counter.output"></span>
  <button data-action="click->counter#addOne">
    Add One
  </button>
</div>
3
// counter_controller.jsimport { Controller } from "stimulus"

export default class extends Controller {
  static targets = [ "output" ]
  
  initialize(){
    this.clickCount = 0
  }
  
  connect(){
    this._updateOutput();
  }

  addOne() {
    this.clickCount++;
    this._updateOutput();
  }
  
  _updateOutput() {
    this.outputTarget.innerText = `You've clicked ${this.clickCount} times`
  }
};

What does it look like?

<!-- index.html -->
<div data-controller="counter">
  <span data-target="counter.output"></span>  <button data-action="click->counter#addOne">
    Add One
  </button>
</div>
3
// counter_controller.js
import { Controller } from "stimulus"

export default class extends Controller {
  static targets = [ "output" ]  
  initialize(){
    this.clickCount = 0
  }
  
  connect(){
    this._updateOutput();
  }

  addOne() {
    this.clickCount++;
    this._updateOutput();
  }
  
  _updateOutput() {
    this.outputTarget.innerText = `You've clicked ${this.clickCount} times`  }
};

What does it look like?

<!-- index.html -->
<div data-controller="counter">
  <span data-target="counter.output"></span>
  <button data-action="click->counter#addOne">    Add One
  </button>
</div>
3
// counter_controller.js
import { Controller } from "stimulus"

export default class extends Controller {
  static targets = [ "output" ]
  
  initialize(){
    this.clickCount = 0
  }
  
  connect(){
    this._updateOutput();
  }

  addOne() {    this.clickCount++;
    this._updateOutput();
  }
  
  _updateOutput() {
    this.outputTarget.innerText = `You've clicked ${this.clickCount} times`
  }
};

When is it useful?

  • A replacement jQuery on older sites
  • You want Progressive Enhancement (It'll work without JavaScript, but is enhanced when JavaScript is ready)
  • You want a little JavaScript within your app, but want a little bit of organisation to the code
  • Small dev team who jump between the frontend & backend

When is it not useful?

  • API Driven Apps - It's possible, but react has better toolage
  • You're already setup using React/Vue & it's working.
  • When no JS would work :D

How can we set it up in Rails!

$ bundle add webpacker
$ bundle
$ bundle exec rails webpacker:install:stimulus

How can we set it up in Rails!

Appending Stimulus setup code to /usr/src/app/app/javascript/packs/application.js
      append  app/javascript/packs/application.js
Creating controllers directory
      create  app/javascript/controllers
      create  app/javascript/controllers/hello_controller.js
      create  app/javascript/controllers/index.js
Installing all Stimulus dependencies
         run  yarn add stimulus from "."
info Direct dependencies
└─ stimulus@1.1.1
Done in 14.14s.
Webpacker now supports Stimulus.js 🎉

How can we set it up in Rails!

▾ app/
  ▸ assets/
  ▸ channels/
  ▸ controllers/
  ▾ javascript/
    ▸ channels/
    ▾ controllers/        hello_controller.js        index.js    ▾ packs/
        application.js  ▸ models/
  ▸ views/

How can we set it up in Rails!

▾ app/
  ▸ assets/
  ▸ channels/
  ▸ controllers/
  ▾ javascript/
    ▸ channels/
    ▾ controllers/
        hello_controller.js        index.js
    ▾ packs/
        application.js
  ▸ models/
  ▸ views/

Questions?

MikeRogers.io
@MikeRogers0 on Twitter

Online I go by @MikeRogers0, normally I have a fairly dull setup which is a pretty enjoyable way to work.

- Here is what I'm aiming to cover - The idea of this talk is give you an idea of the use cases where it's useful, what it's best for - But also where it's not the best choice.

We didn't have many options. Single Page Applications were out there, but in their infancy, along with understanding of progressive enhancement. The end result was lots of spaghetti code.

React & Vue took off, they solved a lot of problems. But they also added an additional moving part of our apps we could potentially avoid.

Not to mention added some new problems HTML kind of solved. I really wanted to just get back to sending HTML to users, with a bit of JavaScript to jazz it up.

The story: - Basecamp wanted that "fluid interfaces set free from the full-page refresh" you can get with SPA - Stimulus came about because they could achieve that with Turbolinks + some organised JS

Then it was added to Rails.

Not to unapproachable!

Controllers have names often linked to their file names, so normally it's pretty easy to be like "Ok I'm looking at this in the HTML, let's find the file"

Targets: You can follow the breadcrumb hints as to what might end up being used for something.

Actions: Again, you can follow the breadcrumbs & it's easy. >> Click the button on this one <<

Lots of places, I had lots of wins replacing jQuery on old rails app with it.