I'm working on a site that has a left column for navigation. Standard stuff. But I wanted a simple control that lets you hide and show the left column.
When I first started using Stimulus, I would create a left_column_controller.js. Within it, in the connect() and disconnect() methods I would add and remove listeners. It worked, but it was verbose and I wasn't enjoying Stimulus. Later, I refactored all my stimulus controllers to extract common interactions. Now I finally "get" Stimulus and I'm loving it!
Check out this example; it's so simple and useful. When I want a special interaction on my page, I create a CSS class that I can add to the element in order to trigger the change I want. For example, adding "hide" collapses the left sidebar, adding "show" reveals additional fields on a form. Here is how I define this collapsible sidebar:
<div data-controller="transition" data-transition-toggle-class="hidden"> <div id="sidebar" class="flex" data-transition-target="transitionable">...</div> <button name="close" type="button" data-action="transition#toggleClass" /> </div>
It's simple, but that's what I love about it. I use this in a half dozen places. Here is the full transition controller.
// transition_controller.js export default class extends Controller { static classes = [ "toggle" ] static targets = [ "transitionable" ] static values = { afterTimeout: Number } connect() { if (this.afterTimeoutValue) setTimeout(() => this.toggleClass(), this.afterTimeoutValue) } toggleClass() { this.transitionableTargets.forEach(element => { this.toggleClasses.forEach(className => { element.classList.toggle(className) }) }) } }
Below is a short video so you can see all the different interactions I get from it; you can see just how versatile this is.
Check out how versatile this is!
When I started thinking this way, it led me to extract multiple reusable controllers like this.
This part of my rails open-source ChatGPT app called HostedGPT. You can find the project on GitHub if you want to use it or help contribute to making it better!
Questions? Comment on this Reddit thread.