Common patterns?


#1

I’m liking Stimulus, and it feels like there’s going to be a proliferation of common needs and patterns that should hopefully emerge.

Has any thought gone into this concept, of where we might be able to share/iterate on patterns using Stimulus?


#2

I was also thinking of something similar. I was thinking to open a thread in this forum where we could post interesting open source projects using Stimulus or examples that we believe could be relevant. A list that would be a bit more curated than just looking a the dependency tree ( https://github.com/stimulusjs/stimulus/network/dependents) to find projects using Stimulus.

We could, therefore, build a list of examples and exchange around best practices.


Post your examples or open source projects
#3

We right now trying to build a live preview of our SaaS platform customization on stimulus + turbolinks.
All our controllers extend from our ApplicationController (aka we do it in Rails).

This ApplicationController provides helpfull shared functionality.

This one of our functions

  /**
   * Get instance of remote controller
   * @param controller - controller name
   * @param id - instance element ID
   */
  connectRemote(controller, id = null) {
    const elementId = id || controller
    const element = document.getElementById(elementId)
    return this.application.getControllerForElementAndIdentifier(element, controller)
  }

We right now trying to build a lot of different things, this why I kinda slow on sharing with code examples. :frowning:
How do you connect your controllers?


#4

Here is a bit of code that was given to me by @nowhereman.

getControllerByIdentifier(identifier) {
  return this.application.controllers.find(controller => {
    return controller.context.identifier === identifier;
  });
}

It works well but only for a child controller to find its parent controller. It also assumes that there is only one parent controller on the same page.

I agree that those helper functions can be placed in a common ApplicationController and extend all your controllers from this supercharged controller.

I might be wrong but I was under the impression that the recent refactoring in the 1.1 tag where a step toward better support for communicating between controllers https://github.com/stimulusjs/stimulus/milestone/2?closed=1.


Having an outer controller that controls inner controller
#5

I feel like this is introducing coupling between controllers, not the method itself, but it’s usage. In some instances I could think of a potential use case; maybe a tabbed interface whereby panes need to communicate with the tab, but this could potentially be handled by a single controller.

This wouldn’t be a an issue if it was clear that a particular controller is dependant on another (for example AngularJS handles this with the require property on directives and components)

Perhaps a pubsub pattern would be more appropriate, or if the TokenObserver is a way of having a props style pattern ala React this would work too. Although that would need to be combined with callbacks as props as well.


#6

Not directly. The TokenObserver refactoring is a change that will make it easier for us to add new attributes. For example, we would like to explore a data-class attribute which lets you map abstract CSS class names to app-specific class names.


#7

PubSub is nice. Right now we do custom events with unique ids. It works pretty much well. I think better API docs in 1.1 will help more people to jump in the dev process.

I don’t think that React props style pattern needed because we don’t do SPA here. (at least library purpose initially not in this)


#8

Today I’ve faced problem of getting action being fired when used Stimulus controller and select2 element.
Didn’t know where to write about it, decided to write here.

What I’ve found - select2 v4 not triggering native events so to have controller action being fired you’ll need to dispatch event manually. Below is example. One more thing - on clear selection (select2:unselect) value cleared after event is triggered.

   $element
      .select2(options)
      .on('select2:select', function() {
        let event = new Event('change', { bubbles: true })
        element.dispatchEvent(event)
      })
      .on('select2:unselect', function() {
        element.value = undefined

        let event = new Event('change', { bubbles: true })
        element.dispatchEvent(event)
      });

Link to select2 issue about native events: https://github.com/select2/select2/issues/1908


#10

Ah, I see, I create a controller for my select2 elements: