Stimulus Cheatsheet

Connect element to controller

  • <div data-controller="country-filter">...</div>
  • or in symfony/twig:
    • {{ stimulus_controller('country-filter') }}
  • or with values:
    • {{ stimulus_controller('country-filter', myValuesArray) }}

Access the controller element

No need for a separate target!

  • connect() {
        console.log(this.element);
    }

Targets

  • <a data-slider-target="nextButton">
  • // slider_controller.js
    export default class extends Controller {
        static targets = [
            'nextButton',
        ];
    
        connect() {
            console.log(this.nextButtonTarget);
        }
    }

Action

  • <div data-action="click->my-controller#doSomething">...</div>

Give a parameter:

  • <div data-action="click->my-controller#doSomething" data-item-id-param="12345">...</div>

Listen to an event @window

  • <div data-action="custom:event-name@window->my-controller#doSomething">...</div>

Values

  • <div
        data-controller="frame"
        data-frame-lazy-value="true"
        <!-- data- $controllerName - $valueName - value -->
    ></div>
  • export default class extends Controller {
    
        static values = {
            lazy: Boolean,
            url: { type: String, default: '/foo' },
        }
    
       connect() {
            console.log(this.lazyValue);
       }
    }
      
    

     

Get the element clicked upon

<button data-action="click->header-nav#toggle">

toggle(event) {
        // Get the clicked element:
        var button = event.currentTarget;

}

Prevent default

foo() {
        event.preventDefault();
        event.stopImmediatePropagation();
}

Communication between controllers

Access another controller

  • <div id="other-controller-id" data-controller="other-controller"></div
  • // foo_controller.js
    
    # this.application is the parent object for all controllers
    const otherController = this.application.getControllerForElementAndIdentifier(
        // the element of the other controller:
        document.getElementById('other-controller-id'), 
        // the other controller's name
        'other-controller'
    );

Alternative

The method described here

did not work for me. Probably because the event receiving element is not an ancestor of the emitter?
Update: maybe params for this.application.getControllerForElementAndIdentifier() were wrong. Try again with the new information above "Access other controller"

Anyways, this worked:

  • In the emitting stimulus controller dispatch a custom event:
    • var customEvent = new CustomEvent("myevent", { detail: { foo: 'bar' }});
      window.dispatchEvent(customEvent);
  • Then bind this event in another controller normally via "data-action" attribute on any element inside the data-controller element:

    • <div data-action="myevent@window->other#anyMethod"></div>
  • This calls anyMethod() inside "other_controller"

    • updateCount(event) {
          console.log(event.detail)
      }

(From https://fullstackheroes.com/tutorials/stimulus/create-custom-events/)

Use Javascript libraries

E.g a module from Bootstrap 5:

  • import { Controller } from '@hotwired/stimulus';
    import { Tab } from 'bootstrap';
    
    export default class extends Controller {
        connect() {
            var tabElement = document.getElementById('my-tab-id');
            const tab = new Tab(tabElement);
            tab.show();      
        }
    }