Parent-Child Controllers for Stimulus

There are a couple of solutions for communicating between controllers, but each time I reach for Stimulus I find myself wanting to be able to compose controllers. This approach follows the declarative nature of targets, classes and values. Declare the parent and children and it will be so.

Here is a fork with the feature, including instructions on how to try it out from GitHub.


Definitions

Define parent and children names in your controller using static properties. Only one parent can be defined per controller.

// controllers/search_controller.js
import { Controller } from "stimulus"

export default class extends Controller {
  static children = [ 'searchResult' ]
  // …
}

// controllers/search_result_controller.js
import { Controller } from "stimulus"

export default class extends Controller {
  static parent = [ 'search' ]
  // …
}

Properties

For each child name defined in the static children array, the following properties are added to your controller, where [name] corresponds to the child’s name:

Kind Name Value
Singuluar this.[name]Child The first matching child
Plural this.[name]Children An array of the children

The parent is available as this.parent regardless of the name specified.

Naming Conventions

Always use camelCase to specify parent and child names, since they map directly to properties on your controller. The names must match the controller identifier of the related controller.

For example, if the child the SearchResultController, then the identifier of the controller in the html is search-result and the child name is searchResult.

Callbacks

Before and after callbacks are available for the registration of both parent and child controllers.

To perform logic when a child is registered with a parent component, define either of the following methods on the parent, where [name] corresponds to the child’s name:

  • before[name]ChildRegistration(childController)
  • after[name]ChildRegistration(childController)

To perform logic when a parent is registered with a child component, define either of the following methods on the child:

  • beforeParentRegistration(parentController)
  • afterParentRegistration(parentController)

I added the sibling controllers, but my update to the wiki entry broke the link above. Here is the updated wiki link for Related Controllers.

I’m also starting to question using links to a wiki that change when the title is changed, so here’s a link to the branch with the changes.