External Store
Bind a slider directly to a minimal, dependency-free reactive store for automatic two-way synchronization.
A control can bind directly to application-owned reactive state instead of owning its value. See External state integration for the full explanation of the binding styles — this example builds the smallest possible store from scratch and binds a slider to it.
Source
A minimal store implementing the ExternalValue<T> shape (get, set,
subscribe):
function createStore<T>(initial: T) {
let value = initial;
const listeners = new Set<(value: T) => void>();
return {
get() {
return value;
},
set(next: T) {
if (Object.is(value, next)) return; // skip no-op — prevents loops
value = next;
for (const listener of listeners) listener(value);
},
subscribe(listener: (value: T) => void) {
listeners.add(listener);
listener(value);
return () => listeners.delete(listener);
},
};
}Binding a slider to it:
const thresholdStore = createStore(128);
const threshold = pp.slider({
label: "Threshold",
value: thresholdStore,
min: 0,
max: 255,
});
thresholdStore.set(180);
console.log(threshold.get()); // 180
threshold.set(200);
console.log(thresholdStore.get()); // 200Notable details
- Passing
thresholdStoreasvalue— instead of a raw number — is what makes this aValueSource<T>binding rather than control-owned state. - Synchronization is automatic and two-way: setting the store updates the slider's displayed value, and dragging the slider updates the store. Neither side polls the other.
- The store's
setskips notifying when the new value isObject.is-equal to the current one — that equality check is what prevents an update loop between the control and the store (see Avoid synchronization loops).