Stimulus JavaScript Framework
Stimulus is a modest, lightweight JavaScript framework designed by Basecamp to augment existing HTML with behavior, rather than taking over the entire front-end rendering. It operates on the principle of connecting JavaScript objects (controllers) to elements on the page using simple HTML data attributes (`data-controller`, `data-action`, `data-target`). It promotes a 'HTML-first' development approach, making it particularly popular in environments like Ruby on Rails with Hotwire (Turbo + Stimulus) where server-rendered HTML is prevalent. The current stable version is 3.2.2. Stimulus is actively maintained with regular updates and follows semantic versioning, introducing new features and occasional breaking changes between major versions. Its key differentiators include its small footprint, convention-over-configuration philosophy, and focus on enhancing server-rendered HTML rather than building single-page applications.
Common errors
-
Uncaught (in promise) TypeError: class constructors must be invoked with 'new'
cause This error often occurs when upgrading to Stimulus 3+ if the application's JavaScript is still being transpiled to ES5, but Stimulus 3 itself is compiled to ES6+. ES5 constructors cannot correctly extend ES6 classes.fixUpdate your JavaScript build configuration (e.g., Babel `browserslist` in `package.json`) to target ES6+ for your application code, explicitly excluding IE11 if it's no longer supported. For example, add `"not IE 11"` to your `browserslist` configuration. -
Stimulus: 'hello' controller not found. Check your `data-controller` attribute and ensure the controller is registered.
cause The `data-controller` attribute in HTML does not match a registered controller identifier, or the controller file is not correctly imported and registered with the Stimulus application.fixVerify that the `data-controller` attribute in your HTML matches the identifier used in `application.register('your-identifier', YourController)` (e.g., `hello` for `hello_controller.js`). Ensure your controller file is correctly imported and that `application.register()` is called. -
this.someTarget is undefined
cause This typically means a `data-[controller]-target="some"` attribute is missing from the HTML element, or the `static targets = ['some']` declaration is missing/incorrect in the controller.fixEnsure the `data-[controller-identifier]-target="some-target-name"` attribute is present in your HTML for the element you wish to access. Also, confirm that `static targets = ['someTargetName']` is correctly defined within your Stimulus controller, using camelCase for the property name.
Warnings
- breaking The Stimulus npm package name changed from `stimulus` to `@hotwired/stimulus` with the release of Stimulus 3. Projects upgrading to v3+ must update their `package.json` and all import paths.
- breaking Stimulus 3 dropped support for Internet Explorer 11. Projects requiring IE11 compatibility should remain on Stimulus 2 or implement polyfills and ensure their JavaScript transpilation targets ES6+.
- breaking In Stimulus 2.0, the syntax for target attributes changed from `data-target="identifier.name"` to `data-[identifier]-target="name"`. While Stimulus 2 provided a console warning for the old syntax, Stimulus 3 fully expects the new scoped syntax.
- deprecated The `data` map API (e.g., `this.data.get('key')`) from Stimulus 1.x was replaced by the more robust 'Values API' and 'CSS Classes API' in Stimulus 2.0. While it might still function, it is no longer documented and considered internal; migration is strongly recommended.
Install
-
npm install stimulus -
yarn add stimulus -
pnpm add stimulus
Imports
- Application
import { Application } from 'stimulus'import { Application } from '@hotwired/stimulus' - Controller
import { Controller } from 'stimulus'import { Controller } from '@hotwired/stimulus' - SpecificController
const SpecificController = require('./controllers/specific_controller')import SpecificController from './controllers/specific_controller'
Quickstart
<!-- index.html -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Stimulus Hello World</title>
</head>
<body>
<div data-controller="hello">
<input data-hello-target="name" type="text" placeholder="Your name">
<button data-action="click->hello#greet">Greet</button>
<p data-hello-target="output"></p>
</div>
<script type="module">
import { Application, Controller } from '@hotwired/stimulus';
// Create a Stimulus application instance
const application = Application.start();
// Define and register the 'hello' controller
class HelloController extends Controller {
static targets = ['name', 'output'];
connect() {
console.log('Hello controller connected!');
this.outputTarget.textContent = 'Enter your name and click greet!';
}
greet() {
const name = this.nameTarget.value;
this.outputTarget.textContent = `Hello, ${name || 'World'}!`;
}
}
application.register('hello', HelloController);
</script>
</body>
</html>