JSFiddle - React, Tailwind, and code Playground
by Takuya Nakajima
HTML
<script src="https://cdn.jsdelivr.net/npm/stimulus@2.0.0/dist/stimulus.umd.min.js"></script>
<div class="Parent" data-controller="parent" data-action="child:change->parent#updateFormula">
<p>Parent</p>
<div class="Parent__children" data-parent-target="children">
<!-- child -->
</div>
<button type="button" data-action="click->parent#add">
add child
</button>
<div class="Parent__value" data-parent-target="value">-</div>
<template data-parent-target="template">
<div class="Child" data-controller="child">
<p>Child</p>
<input type="text" data-parent-target="input" data-action="input->child#change">
<button data-action="click->child#remove">delete</button>
</div>
</template>
</div>
CSS
* {
margin: 0;
padding: 0;
}
body {
margin: 20px;
}
.Parent {
padding: 20px;
border: 1px solid #000;
}
.Parent__value {
margin-top: 20px;
padding: 10px;
background: #dedede;
}
.Child {
padding: 10px;
background: skyblue;
border: 1px solid #000;
}
input,button {
padding: 5px;
}
JavaScript
const {Application, Controller} = Stimulus;
const app = Application.start();
class Base extends Controller { // from hey.com
dispatch(eventName, { target = this.element, detail = {}, bubbles = true, cancelable = true } = {}) {
const type = `${this.identifier}:${eventName}`
const event = new CustomEvent(type, { detail, bubbles, cancelable })
target.dispatchEvent(event)
return event
}
}
app.register('parent', class extends Base {
static targets = ['children', 'template', 'value', 'input'];
initialize() {
this.add();
}
add() {
let child = this.templateTarget.content.cloneNode(true);
this.childrenTarget.append(child);
}
updateFormula() {
let formula = this.inputTargets.map(input => input.value).join('/');
this.valueTarget.innerHTML = formula || '-';
}
});
app.register('child', class extends Base {
remove() {
let parent = this.element.parentNode;
this.element.remove();
this.dispatch('change', {target: parent});
}
change() {
this.dispatch('change');
}
})