Skip to content

Instantly share code, notes, and snippets.

@bennadel
Created March 14, 2023 11:38
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bennadel/82397f0b5b495b867702dd9ea3feaef6 to your computer and use it in GitHub Desktop.
Save bennadel/82397f0b5b495b867702dd9ea3feaef6 to your computer and use it in GitHub Desktop.
Using Nested Stimulus Controllers With Hotwire And Lucee CFML
<cfscript>
items = [
{ id: 1, name: "Item One" },
{ id: 2, name: "Item Two" },
{ id: 3, name: "Item Three" }
];
</cfscript>
<cfmodule template="./tags/page.cfm">
<cfoutput>
<h2>
Welcome to My Site
</h2>
<!--- There is a PARENT CONTROLLER on the list. --->
<ul
data-controller="parent"
data-action="child:hello->parent##logEvent">
<cfloop item="item" array="#items#">
<!--- There is a CHILD CONTROLLER on each list item. --->
<li
data-controller="child"
data-child-id-value="#encodeForHtmlAttribute( item.id )#">
#encodeForHtml( item.name )#
<!---
Even though we are inside the CHILD controller scope, we are still
technically in the SCOPE of the PARENT controller as well. As
such, we can reach outside of the child scope and trigger actions
on the parent controller. In this case, we're going to include
child-related data as PARAMS on the triggered event.
--->
<button
data-action="parent##logAction"
data-parent-child-id-param="#encodeForHtmlAttribute( item.id )#"
data-parent-child-data-param="#encodeForHtmlAttribute( serializeJson( item ) )#">
Trigger Parent Action
</button>
<!---
We can also emit / trigger / broadcast / dispatch events from the
CHILD controller up the DOM tree (like any non-custom event). The
PARENT controller can then listen for these events in its own
action bindings.
--->
<button data-action="child##emitEvent">
Emit Child Event
</button>
</li>
</cfloop>
</ul>
</cfoutput>
</cfmodule>
// Import core modules.
import { Application } from "@hotwired/stimulus";
import { Controller } from "@hotwired/stimulus";
import * as Turbo from "@hotwired/turbo";
// ----------------------------------------------------------------------------------- //
// ----------------------------------------------------------------------------------- //
class ParentController extends Controller {
/**
* I log the event when the button in the CHILD HTML is used to invoke an action on
* this PARENT controller instance.
*/
logAction( event ) {
console.group( "Parent Action [%s]", event.type );
console.log( "Child ID:", event.params.childId );
console.log( "Child Data:", event.params.childData );
console.groupEnd();
}
/**
* I log the event that the CHILD controller emits up the DOM tree.
*/
logEvent( event ) {
console.group( "Parent Event [%s]", event.type );
console.log( "Child ID:", event.detail.id );
console.groupEnd();
}
}
class ChildController extends Controller {
static values = {
id: Number
};
/**
* I emit a demo event up the DOM tree where any higher-up controller can bind to it.
*/
emitEvent() {
this.dispatch(
"hello",
{
detail: {
id: this.idValue
}
}
);
}
}
// ----------------------------------------------------------------------------------- //
// ----------------------------------------------------------------------------------- //
window.Stimulus = Application.start();
// When not using the Ruby On Rails asset pipeline / build system, Stimulus doesn't know
// how to map controller classes to data-controller attributes. As such, we have to
// explicitly register the Controllers on Stimulus startup.
Stimulus.register( "parent", ParentController );
Stimulus.register( "child", ChildController );
<ul data-controller="parent">
<li data-controller="child"> ... </li>
<li data-controller="child"> ... </li>
<li data-controller="child"> ... </li>
</ul>
<button
data-action="parent##logAction"
data-parent-child-id-param="#encodeForHtmlAttribute( item.id )#"
data-parent-child-data-param="#encodeForHtmlAttribute( serializeJson( item ) )#">
Trigger Parent Action
</button>
<button data-action="child##emitEvent">
Emit Child Event
</button>
<ul
data-controller="parent"
data-action="child:hello->parent##logEvent">
....
</ul>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment