Declarative Bindings - cynchro/OldSchoolFrontFrame GitHub Wiki

Declarative Bindings

OLS uses data-* HTML attributes to connect your state to the DOM without writing imperative DOM manipulation code.


Display bindings

data-bind

One-way binding. Updates the element's textContent whenever the state path changes.

<span data-bind="count"></span>
<p data-bind="user.name"></p>
<td data-bind="items.0.price"></td>

Supports dot-notation for nested paths.


data-model

Two-way binding for form inputs. Updates the DOM when state changes and updates state when the user types.

<input data-model="query" type="text" />
<textarea data-model="description"></textarea>
<input data-model="agreed" type="checkbox" />
<select data-model="role">
  <option value="admin">Admin</option>
  <option value="user">User</option>
</select>

The binding uses the appropriate DOM property for each input type (value, checked, etc.).


data-for

Renders a list by repeating a <template> for each item in an array.

<!-- List container -->
<ul data-for="products" data-template="product-tpl"></ul>

<!-- Template (hidden) -->
<template id="product-tpl">
  <li>
    <span data-bind="name"></span> — $<span data-bind="price"></span>
  </li>
</template>
defineModule({
  state: () => ({
    products: [
      { name: 'Widget', price: 9.99 },
      { name: 'Gadget', price: 19.99 },
    ],
  }),
});

Inside a data-for template, data-bind paths are relative to each list item.


Event bindings

Attach event handlers by referencing a method name. The method receives ctx as the first argument and the native DOM event as the second.

data-click

<button data-click="save">Save</button>
methods: {
  save(ctx, event) {
    // handle click
  },
},

data-submit

<form data-submit="handleSubmit">...</form>

Calls event.preventDefault() automatically.

data-input

Fires on every keystroke.

<input data-input="onSearch" type="text" />

data-change

Fires when the input loses focus with a changed value (standard change event).

<select data-change="onRoleChange">...</select>

data-keyup / data-keydown

<input data-keyup="onKey" />

data-blur / data-focus

<input data-blur="validate" />
<input data-focus="clearError" />

Attribute modifiers

Binding to store state

Prefix any path with store. to bind to the global store instead of module state:

<span data-bind="store.currentUser.name"></span>
<input data-model="store.filters.query" />

Notes

  • All data-bind and data-model paths are evaluated relative to ctx.state by default.
  • data-for renders are re-computed whenever the array is replaced (e.g. ctx.state.items = newArray).
  • In-place array mutations (push, splice) are tracked automatically through the Proxy.
  • Event handler methods are looked up in the module's methods object by name string.
⚠️ **GitHub.com Fallback** ⚠️