Stimulus: A modest JavaScript framework for the HTML you already have

News

February 1st, 2018

stimulus-javascript-framework.jpg

The team over at Basecamp has released a new Javascript framework (v1.0.0) called Stimulus, available as of January 30th. Stimulus is quite a departure from some of the more popular frontend JavaScript frameworks, touting more separation of concerns between your HTML’s content and behavior:

Stimulus is a JavaScript framework with modest ambitions. Unlike other frameworks, Stimulus doesn’t take over your application’s entire front-end. Rather, it’s designed to augment your HTML by connecting elements to JavaScript objects automatically.

The documentation explains that the separation between your HTML’s behavior and content is bridged by data-controller‘s from HTML to JavaScript.

Here’s a simple example, which I believe is pretty straightforward:

1<div data-controller="hello">
2 <input type="text">
3 <button data-action="click->hello#greet">Greet</button>
4</div>

Here’s the hello controller code:

1// src/controllers/hello_controller.js
2import { Controller } from "stimulus"
3
4export default class extends Controller {
5 greet() {
6 console.log("Hello, Stimulus!", this.element)
7 }
8}

The data-action="click->hello#greet" button attribute is the ticket here; you can break down the value as follows:

  • click is the event name
  • hello is the controller identifier
  • greet is the name of the method to invoke

We can mark important elements as a target to reference them in the controller:

1<div data-controller="hello">
2 <input data-target="hello.name" type="text">
3 <button data-action="click->hello#greet">Greet</button>
4</div>

The data-target value is the controller name and the target name. Here’s how you would reference this value in a controller:

1// src/controllers/hello_controller.js
2import { Controller } from "stimulus"
3
4export default class extends Controller {
5 static targets = [ "name" ]
6
7 greet() {
8 const element = this.nameTarget
9 const name = element.value
10 console.log(`Hello, ${name}!`)
11 }
12}

Since this is a JavaScript class, we can benefit from a name getter:

1// src/controllers/hello_controller.js
2import { Controller } from "stimulus"
3
4export default class extends Controller {
5 static targets = [ "name" ]
6
7 greet() {
8 console.log(`Hello, ${this.name}!`)
9 }
10
11 get name() {
12 return this.nameTarget.value
13 }
14}

These samples are from the Hello Stimulus introduction. Stimulus also works with Turbolinks out-of-the-box, which is useful for speeding traditional server-side applications.

You should check out the installation guide and the stimulus starter to get started with the framework.

Using Stimulus With Laravel

I also started experimenting with Stimulus, Turbolinks, and Laravel in a quick GitHub repository paulredmond/stimulus-laravel-demo. Here’s the gist of everything I needed to do to get it running:

1yarn add stimulus turbolinks
2yarn add --dev babel-plugin-transform-class-properties

Add the following to your .babelrc file in the root of the project:

1{
2 "plugins": ["transform-class-properties"],
3 "presets": [
4 ["env", { "modules": false }]
5 ]
6}

Next, create a resources/assets/js/controllers folder and replace the following in the resources/assets/js/app.js file:

1var Turbolinks = require("turbolinks")
2Turbolinks.start()
3
4import { Application } from "stimulus"
5import { definitionsFromContext } from "stimulus/webpack-helpers"
6
7const application = Application.start()
8const context = require.context("./controllers", true, /\.js$/)
9application.load(definitionsFromContext(context))

One last important note:

Turbolinks needs to be in the <head> of the HTML document. The <body> gets replaced when you navigate after getting the document via XHR, thus, the script needs to be outside of the <body> tag.

So just add your app.js file in the head like this:

1<head>
2 <!-- ... -->
3 <link href="{{ mix('css/app.css') }}" rel="stylesheet" type="text/css" />
4 <script src="{{ mix('js/app.js') }}"></script>
5</head>

Cheers!

Filed in:

Paul Redmond

Full stack web developer. Author of Lumen Programming Guide and Docker for PHP Developers.