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

News

February 1st, 2018

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

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:

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

Here’s the hello controller code:

// src/controllers/hello_controller.js
import { Controller } from "stimulus"
 
export default class extends Controller {
greet() {
console.log("Hello, Stimulus!", this.element)
}
}

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:

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

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

// src/controllers/hello_controller.js
import { Controller } from "stimulus"
 
export default class extends Controller {
static targets = [ "name" ]
 
greet() {
const element = this.nameTarget
const name = element.value
console.log(`Hello, ${name}!`)
}
}

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

// src/controllers/hello_controller.js
import { Controller } from "stimulus"
 
export default class extends Controller {
static targets = [ "name" ]
 
greet() {
console.log(`Hello, ${this.name}!`)
}
 
get name() {
return this.nameTarget.value
}
}

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:

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

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

{
"plugins": ["transform-class-properties"],
"presets": [
["env", { "modules": false }]
]
}

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

var Turbolinks = require("turbolinks")
Turbolinks.start()
 
import { Application } from "stimulus"
import { definitionsFromContext } from "stimulus/webpack-helpers"
 
const application = Application.start()
const context = require.context("./controllers", true, /\.js$/)
application.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:

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

Cheers!

Filed in:

Paul Redmond

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