-
Notifications
You must be signed in to change notification settings - Fork 442
Description
So this is a pattern I frenquently come accross when using Stimulus on forms: reacting to <input>'s value change like displaying parts of a form according to a checkbox. Currently, the way I implement it is like this:
<input type="checkbox" data-action="[identifier]#OnChange" />
<fieldset data-[identfier]-target="fieldset">…</fieldset>import {Controller} from "Stimulus";
class FormController extends Controller {
static targets = ["fieldset"]
onChange({target: {checked}}) {
if(checked) { this.fieldsetTarget.setAttribute("hidden", "hidden"); }
else { this.fieldsetTarget.removeAttribute("hidden", "hidden"); }
}
}However, since events are only fired on user interactions, this forces us to add some boilerplate to get the correct display upon init:
<input data-[identfier]-target="checkbox" type="checkbox" data-action="[identifier]#OnChange" />
<fieldset data-[identfier]-target="fieldset">…</fieldset>import {Controller} from "Stimulus";
class FormController extends Controller {
static targets = ["fieldset", "checkbox"]
onChange({target: {checked}}) {
this.mutateFieldsetVisibility(checked)
}
checkboxTargetConnected(el) {
this.mutateFieldsetVisibility(el.checked);
}
mutateFieldsetVisibility(visible) {
if(checked) { this.fieldsetTarget.setAttribute("hidden", "hidden"); }
else { this.fieldsetTarget.removeAttribute("hidden", "hidden"); }
}
}Just to get the correct init, we need to declare a target on the input that will only be used once in the controller's lifetime.
What I propose propose to add a new data-[identifier]-model that would work exactly like Vue's v-model:
<input data-[identfier]-model="checkbox" type="checkbox" />
<fieldset data-[identfier]-target="fieldset">…</fieldset>import {Controller} from "Stimulus";
class FormController extends Controller {
static targets = ["fieldset"]
static models = ["checkbox"]
checkboxModelChange(value) {
// or can be accessed through `this.checkboxModel`
if(value) { this.fieldsetTarget.setAttribute("hidden", "hidden"); }
else { this.fieldsetTarget.removeAttribute("hidden", "hidden"); }
}
}If this is too inconvenient to implement, can you indicate me how to leverage Stimulus' API to implement it as an extension similar to stimulus-use? This would require dynamic target and value binding and I don't believe this can be done after controller's initialize() lifecycle phase, can it?