Stimulus is a “modest JavaScript framework”, built by the folks at Basecamp who brought you Rails.
It is, in many ways, the opposite of other modern frameworks available today. While you might see some similar concepts and naming, Stimulus is very different in some fundamental ways. We’ll discuss those differences briefly, and then build our first application with Stimulus.
The DOM: A Place for State?
The core concepts of many modern frameworks lie in separating “state” from the “DOM”. In this way, the DOM acts only as a client to the data it is representing.
Stimulus flips this concept on its head, and instead relies on the DOM to hold state.
What this ultimately means is that Stimulus is best suited for applications that serve HTML (rather than, for example, integrating with a JSON API).
With Stimulus, you won’t see HTML templates. Instead, you will see data-*
attributes that connect the HTML to the JavaScript application.
This also means you won’t see things like each
or map
loops like you might see in Handlebars or React.
Stimulus doesn’t hold the job of rendering HTML unless you explicitly create that functionality.
So… What Does It Do?
So Stimulus doesn’t render templates. Rather it is built to connect actions and events you take on the front end of an application to controllers on the back end.
Stimulus uses three concepts to accomplish this: targets, controllers, and actions.
But before we get too far in, let’s go ahead and get Stimulus up and running on your computer!
Setup
This setup assumes you have already installed a recent version of NodeJS on your computer. Head over to nodejs.org if you haven’t done this already.
We’ll be using a basic static index.html
file that will initially look like this:
Note: We won’t actually cover any styling or build processes for the CSS in this tutorial.
Next, create a folder called src
. Inside of src
, create another folder called controllers
and a single index.js
file.
We’ll be using Webpack to build our JavaScript application, since Stimulus uses some advanced features of JavaScript that won’t work directly in browsers.
Create a file in the root of your project called package.json
that has the following contents:
{ "name": "wdstimulus", "version": "1.0.0", "description": "Stimulus Introduction", "scripts": {}, "author": "Your Name", "license": "ISC", "devDependencies": { "@babel/core": "^7.0.0-beta.39", "@babel/preset-env": "^7.0.0-beta.39", "babel-loader": "^8.0.0-beta.0", "babel-preset-stage-0": "^6.24.1", "stimulus": "^1.0.0", "webpack": "^3.10.0" } }
Note: these versions will change in the future, and we recommend staying up to date with the latest version of any tool as much as is practical.
You can also generate this file using npm init
and installing dependencies one by one using npm install [package-name]
.
This file includes everything we need to create a browser-compatible build of our Stimulus application. From the root of the application, run npm install
. This will install these dependencies in the node_modules
directory inside your application.
Next, we’ll create a configuration file so Webpack knows what we want it to do with our files when we save them. In the same root directory where the package.json
is located, created a file called webpack.config.js
, and add these contents:
module.exports = { module: { rules: [ { test: /.js$/, exclude: /(node_modules)/, use: { loader: 'babel-loader', options: { presets: ["@babel/env"], plugins: ["transform-class-properties"] } } } ] } };
This file essentially tells Webpack to compile our JavaScript using the env preset. We have the stage-0 preset available in our node modules, and we’ve also added the required transform-class-properties plugin.
The last step to be ready for a Stimulus application is to fill in our index.js
file with the following contents:
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))
This code comes directly from the Stimulus docs. It performs some magic to allow us to use a conventional naming structure when creating our application code.
The naming of your files actually matters to Stimulus if you use this index.js
code (this nuance is something Rails developers will find familiar).
Now that we’re all set up, let’s make sure our Webpack build works. From the root directory, run the following command:
npx webpack src/index.js dist/bundle.js --watch
The npx
portion of this command is a convenient way of running binaries that are located in the node_modules
directory. This command will watch changes to your JavaScript files and rebuild your application as you make those changes.
As long as you don’t see errors in your console, you are good to go!
Controllers
If you’re familiar with Rails or Laravel, the concept of controllers might be easy to adopt for you.
Think of a controller in the case of Stimulus as a JavaScript class that contains some methods and data that work together.
A controller might look like this in Stimulus:
// src/controllers/refreshable_controller.js import { Controller } from "stimulus" export default class extends Controller { }
There are a few important points to note about this controller. First, the controller is both HTML and JavaScript. The data-controller
attribute is what tells the JavaScript to create a new instance of the class.
Another interesting characteristic to notice is the fact that the class name isn’t found anywhere in the controller class itself. This happens because of the line application.load(definitionsFromContext(context))
in the index.js
file. This line loads the application code and uses the file names to infer class names. This might be confusing at first, but once you start using this convention regularly, it becomes much more fluid.
Actions
An action is what it sounds like: a procedure you want to take place after a particular event from a user. For our refresh controller, we want to perform a refresh of a particular area of content when a button is clicked. In this case, our action could be called refresh
.
// src/controllers/refreshable_controller.js import { Controller } from "stimulus" export default class extends Controller { refresh(){ console.log("refresh!") } }
But just having this action method available in our controller doesn’t do anything. We need to connect it to our HTML.
When the user clicks on the button in this HTML, it would run the refresh action in the controller.
Now, how can we use this action to do something on the page?
Targets
Stimulus also uses a concept called “Targets” to connect to important elements on the page. We’ll use this to manage a container element that holds the content we want to refresh.
// src/controllers/refreshable_controller.js import { Controller } from "stimulus" export default class extends Controller { static targets = [ "content" ] refresh(){ this.contentTarget.innerHTML = "Refresh!" } }
In this example, we have all three concepts of Stimulus represented. A refreshable
controller, a refresh
action, and a content
target.
If you’re looking closely, you’ll see something in this code that might catch you off guard: direct manipulation of the DOM. This is one way that Stimulus is different from other frameworks. Direct manipulation of DOM elements isn’t only possible, it is encouraged.
This also means that if you are well versed in jQuery or vanilla JavaScript and browser APIs, you can take advantage of that knowledge! For example, a jQuery-powered version of the refresh method might look like this:
// src/controllers/refreshable_controller.js import { Controller } from "stimulus" import $ from 'jquery'; // requires adding jQuery to package.json export default class extends Controller { static targets = [ "content" ] refresh(){ let target = this.contentTarget; $.get("/content", function(content){ $(target).html(content) }) } }
Stimulus doesn’t get in the way if you want to use other tools you are already familiar with.
That’s All for This Crash Course!
You now have enough info to get started building more maintainable applications with Stimulus! The developers who created Stimulus remind us that rules and trends can be broken, and sometimes we can break away from the “best practices” and just do something that works for us.
Enjoy diving into Stimulus!
Further Reading
- stimulusjs.org
- The Origin of Stimulus
- Stimulus Discourse
Powered by WPeMatico