Created
March 14, 2023 11:38
-
-
Save bennadel/82397f0b5b495b867702dd9ea3feaef6 to your computer and use it in GitHub Desktop.
Using Nested Stimulus Controllers With Hotwire And Lucee CFML
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<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> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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 ); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<ul data-controller="parent"> | |
<li data-controller="child"> ... </li> | |
<li data-controller="child"> ... </li> | |
<li data-controller="child"> ... </li> | |
</ul> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<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> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<button data-action="child##emitEvent"> | |
Emit Child Event | |
</button> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<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