Stimulus
Von Bettina Bröthaler am 20.02.2022
https://stimulus.hotwired.dev/
Stimulus, ein modernes JavaScript-Framework, das ein bestehendes HTML-DOM problemlos ergänzen kann. Aber warum ist Stimulus ein nützliches Tool?
Alles in allem ist Stimulus eine ~30kb große Bibliothek, die kleine, wiederverwendbare JavaScript Bausteine beinhaltet, welche durch kleine Hinweise in HTML inkludiert werden können.
Aber wie funktioniert das Ganze?
Controller
Ein Controller
ist die grundlegende Strukturierungseinheit einer Stimulus-Anwendung.
import { Controller } from "@hotwired/stimulus"
export default class extends Controller {
// …
}
Im Dateinamen werden mehrere Worte durch Unterstriche oder Bindestriche getrennt:
controllers/sidebar_controller.js
controllers/delete_modal_controller.js
Identifiers
sind die Namen, die verwendet werden um eine Controller-Klasse zu referenzieren. Wenn ein Element mittels data-controller
Attribute hinzugefügt wird, liest Stimulus den Identifier aus dem Attribut und erstellt eine neue Instanz der Controller-Klasse.
<div data-controller="sidebar"></div>
Hier hat das Element den Controller controllers/sidebar_controller.js
Webpack
Wenn Stimulus beispielsweise mit Webpack genutzt wird, gibt es die Möglichkeit das Paket @hotwired/stimulus-webpack-helpers
zu nutzen um die Controller-Klassen automatisch zu laden und zu registrieren:
import { Application } from "@hotwired/stimulus"
import { definitionsFromContext } from "@hotwired/stimulus-webpack-helpers"
window.Stimulus = Application.start()
const context = require.context("./controllers", true, /\\.js$/)
Stimulus.load(definitionsFromContext(context))
Manuelle Einbindung
Ohne den Webpack Helper muss jede Controller-Klasse manuell geladen und registriert werden z.B.:
import SidebarController from "./controllers/sidebar_controller"
application.register("sidebar", SidebarController)
Actions
Actions sind die Events, die vom DOM ausgeführt werden.
<div data-controller="sidebar">
<button data-action="click->sidebar#open">…</button>
</div>
// controllers/sidebar_controller.js
import { Controller } from "@hotwired/stimulus"
export default class extends Controller {
open(event) {
// …
}
}
click
ist der Name des Event Listenerssidebar
ist der Name des Controllersopen
ist der Name der Methode
Hier gibt es auch die Möglichkeit für globale Events, also Event Listeners, die auf das Fenster oder das Dokument hören. Beispielsweise:
<div data-controller="sidebar"
data-action="resize@window->sidebar#layout">
</div>
Targets
Targets referenzieren bestimmte Elemente beim Namen.
<div data-controller="sidebar">
<div data-sidebar-target="overlay"></div>
</div>
Die Targets werden im Controller mittels einem static targets
Array definiert
// controllers/sidebar_controller.js
import { Controller } from "@hotwired/stimulus"
export default class extends Controller {
static targets = [ "overlay" ]
}
Jedes Target kann mittels this.[name]Target
innerhalb des Controllers aufgerufen werden. Hier also z.B. this.overlayTarget
.
Values
Ähnlich können HTML Attribute für Daten verwendet werden.
<div data-controller="sidebar"
data-sidebar-color-value="#000">
</div>
// controllers/sidebar_controller.js
import { Controller } from "@hotwired/stimulus"
export default class extends Controller {
static values = {
color: String
}
}
Auf diesen Wert kann dann mittels this.colorValue
zugegriffen werden.
Lifecycle Callbacks
Spezielle Methoden, ermöglichen es mit den Lifecycle Callbacks
direkt zu reagieren, wenn ein Controller eine Verbindung zu einem Dokument herstellt oder getrennt wird.
Methoden:
Quelle: https://stimulus.hotwired.dev/reference/lifecycle-callbacks (15.02.2022, 12:10)
Connection
Ein Controller wird verbunden wenn entweder eines seiner Elemente im Dokument vorhanden ist oder sein Identifier in einem data-controller
Attribute aufgerufen wird.
Wenn ein Controller verbunden wird, wird die connect()
Methode aufgerufen.
Ein Target wird verbunden wenn entweder das Element im Dokument innerhalb des jeweiligen Controller Elements vorhanden ist oder sein Identifier vorhanden ist (data-{identifier}-target
).
Wenn ein Target verbunden wird, wird die [name]TargetConnected()
Methode aufgerufen, dies wird außerdem VOR der allgemeinen connect()
Methode aufgerufen.
Disconnection
Ein verbundener Controller wird getrennt wenn eine “verbindenden” Bedingungen nicht mehr zutrifft. Wenn also beispielsweise das Element vom DOM, das Eltern Element enfernt oder ersetzt wird oder auch wenn das data-controller
Attribute entfernt oder überschrieben wird.
In einem dieser Fälle wird die Methode disconnect()
aufgerufen.
Die gleiche Vorgehensweise trifft auf die Trennung eines Targets zu hier wird [name]TargetDisconnected()
aufgerufen. Dies wird ebenfalls VOR der Controller disconnect()
Funktion ausgeführt.
Sidebar Beispiel
Hier ein Beispiel für eine einfache “Sidebar” Erstellung. In diesem Beispiel wird anhand von Buttons eine Sidebar ein- bzw. ausgeblendet. Hier wird mittels Webpack das script.js
generiert, in welchem wie oben beschrieben, die Controller Klasse eingebunden wird.
Die Buttons rufen die Funktionen open()
und close()
auf, die im sidebar_controller
definiert sind. In den Funktionen wird die CSS Klasse .hidden
hinzugefügt bzw. entfernt.
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Stimulus</title>
<link rel="stylesheet" href="/dist/css/style.css">
</head>
<body data-controller="sidebar">
<div class="sidenav hidden" data-action="click->sidebar#close" data-sidebar-target="overlay">
<button>Close Sidebar</button>
</div>
<main>
<h1>Stimulus Sidebar</h1>
<button data-action="click->sidebar#open">Open Sidebar</button>
</main>
<script src="/dist/javascript/script.js"></script>
</body>
</html>
style.scss
.sidenav {
height: 100%;
width: 200px;
position: fixed;
z-index: 1;
top: 0;
left: 0;
background-color: #111;
overflow-x: hidden;
padding: 2rem;
}
.hidden {
visibility: hidden;
}
main {
padding: 2rem;
}
script.js
import { Application } from "@hotwired/stimulus"
import { definitionsFromContext } from "@hotwired/stimulus-webpack-helpers"
window.Stimulus = Application.start()
const context = require.context("./controllers", true, /\\.js$/)
Stimulus.load(definitionsFromContext(context))
sidebar_controller.js
import { Controller } from "@hotwired/stimulus"
export default class extends Controller {
static targets = [
"overlay"
]
connect() {
console.log("Sidebar Controller connected");
}
open() {
console.log("OPEN");
this.overlayTarget.classList.remove("hidden");
}
close() {
console.log("CLOSE");
this.overlayTarget.classList.add("hidden");
}
}
Quellen
https://stimulus.hotwired.dev/
https://pspdfkit.com/blog/2018/introduction-to-stimulus-js/
https://gist.github.com/mrmartineau/a4b7dfc22dc8312f521b42bb3c9a7c1e
https://www.smashingmagazine.com/2020/07/introduction-stimulusjs/
https://egghead.io/lessons/javascript-fire-a-stimulus-controller-action-on-a-click-event
The comments are closed.