stimulus-value-bindings
v0.1.0
Published
One-way reactive DOM bindings for Stimulus JS
Maintainers
Readme
stimulus-value-bindings 🪢
Reactive DOM value bindings for Stimulus JS.
Overview
stimulus-value-bindings allows DOM element attribute values to be reactively bound to Stimulus controller values
so that the DOM attributes are automatically updated when their bound value property changes.
Bindings are:
- reactive - every time a value is changed any bound attributes (or text contents) in the DOM are automatically (and transparently) updated to reflect the changes.
- one-way - the flow of updates is always from the controller to the DOM. Direct manipulation to bound attributes in the DOM will not result in the controller values being updated.
stimulus-value-bindings can help you drastically reduce the amount of boring something-has-changed-and-now-the-DOM-needs-updating code in your Stimulus JS controllers.
[!WARNING] This documentation is a work-in-progress! Please open an issue if you are having problems.
Simple counter example
The example below is a simple 'counter' example that should help to demonstrate how reactive value bindings work.
▶️ View this example running in JSBin
// counter-controller.js
import { Controller } from "@hotwired/stimulus";
import { useValueBindings } from "stimulus-value-bindings";
export default class extends Controller {
static values = {
count: Number
}
connect(){
useValueBindings(this);
}
increment(){
this.countValue++;
}
decrement(){
this.countValue--;
}
}<div data-controller="counter">
<span id="count" data-counter-bind-text="countValue">0</span>
<button data-action="counter#increment">+</button>
<button data-action="counter#decrement">-</button>
</div>When the + or - buttons are clicked the span#count element text content will be automatically be updated to reflect the current value of the count controller value. The counter display is kept in sync with the count value without needing to manually update the DOM after each change.
Installation
Add the stimulus-value-bindings package to your package.json:
Using NPM:
npm i stimulus-value-bindings --saveUsing Yarn:
yarn add stimulus-value-bindingsUsage
The stimulus-value-bindings package exports a useValueBinding function that can be used to add reactive value binding functionality to controllers.
import { Controller } from "@hotwired/stimulus";
import { useValueBindings } from "stimulus-value-bindings";
export default class extends Controller {
connect(){
useValueBindings(this);
}
}Alternatively, the package also exports a 'ready to go' ValueBindingsController base controller if you prefer to extend rather than compose your classes:
import { ValueBindingsController } from "stimulus-value-bindings";
export default class extends ValueBindingsController {
// ...
}You can then delare controller values in the usual way, and bind DOM element attribute values and content to them using binding data attributes.
// read-more-controller.js
import { Controller } from "@hotwired/stimulus";
import { useValueBindings } from "stimulus-value-bindings";
export default class extends Controller {
static values = {
showMore: Boolean,
buttonText: String
}
connect(){
useValueBindings(this);
}
toggle(){
this.openValue = !this.openValue;
this.buttonTextValue = this.openValue ? "read less" : "read more";
}
}<div data-controller="read-more">
<p>This is the summary content.</p>
<button data-action="read-more#toggle" data-read-more-bind-text="buttonTextValue">read more</button>
<p data-read-more-bind-hidden="!showMore" data-read-more-bind-aria-expanded="showMore" hidden>
This is the additional content.
</p>
</div>In the example above, clicking the read more button will toggle the hidden attribute on the 'additional content' div to hide or show it. The button text will additonally be updated to read more or read less according to whether the additional content is currently hidden or shown respectively.
Adding bindings to elements
Bindings are declared on DOM elements using data attributes with the following format:
data-[identifier]-bind-[bindingType]="[valueName]"[identifier]: The identifier of the target controller[bindingType]: See below for the types of bindings available.[valueName]The name of the value getter property to bind to.
Attribute bindings
The values of DOM element attributes can be bound to controller values using attribute bindings.
data-[identifier]-bind-[attribute-name]="[valueName]"For example:
// defined in example-controller.js
static values = {
progress: 0
}<div data-controller="example">
<h4>Uploading...</h4>
<progress data-example-bind-value="progressValue" max="100"></progress>
</div>Boolean attributes
Boolean attributes will be added or removed according to the truthiness of the value they are bound to.
// defined in example-controller.js
static values = {
hidden: Boolean,
}<div data-controller="example">
<div data-example-bind-hidden="hiddenValue">some content</div>
</div>- When
hiddenValueistrue, thehiddenattribute will be added to the bound element. - When
hiddenValueisfalse, thehiddenattribute will be removed from the element.
Element textContent binding
The textContent of elements can be bound to controller values using text bindings.
data-[identifier]-bind-text="[valueName]"For example:
// defined in example-controller.js
static values = {
count: Number
}<div data-controller="example">
<span data-example-bind-text="countValue">0</span>
</div>Element bindings
Elements can be bound to Object-type values. An attribute or content binding will be created for each of the object's properties.
data-[identifier]-bind="[valueName]"For example:
// defined in example-controller.js
static values = {
input: {
type: Object,
default: {
value: "default value",
disabled: true
}
}
}<div data-controller="example">
<input data-example-bind="inputValue">
<!-- renders: <input disabled="disabled" value="default value"> -->
</div>Credits
stimulus-value-bindings is inspired by (and borrows code from!) the x-bind functionality in Alpine JS.
License
stimulus-value-bindings is available as open source under the terms of the MIT License.
