Forms & Binding
ly-model provides seamless two-way data synchronization across all HTML form controls — text, textarea, numeric inputs, checkboxes, radios, and selects.
Text inputs
Bind an input to a state property. User typing updates state instantly, while programmatic state mutations update the input control.
<div>
<script>
const formDemo = Lyap.scope('formDemo');
formDemo.state({ username: '' });
</script>
<input type="text" ly-model="formDemo.username">
<p>Hello, <span ly-text="formDemo.username"></span>!</p>
</div>
Live previewlyap
Hello, !
Modifiers
Modifiers attach to ly-model to refine synchronization behavior:
| Modifier | Purpose |
|---|---|
.trim | Trims whitespace from string values before updating state. |
.number | Parses numeric values to finite numbers. |
.lazy | Listens for change instead of input events (syncs on blur/enter). |
<input type="text" ly-model.trim="user.username">
<input type="number" ly-model.number="user.age">
<textarea ly-model.lazy="user.bio"></textarea>
Checkboxes & radios
A single checkbox binds to a boolean state property. A checkbox group sharing the same ly-model target array binds to an array of selected values. Radios bind to the selected value.
<!-- Single boolean checkbox -->
<label>
<input type="checkbox" ly-model="form.agree"> Accept Terms
</label>
<!-- Array checkbox group -->
<label><input type="checkbox" ly-model="form.interests" value="coding"> Coding</label>
<label><input type="checkbox" ly-model="form.interests" value="design"> Design</label>
<!-- Radio group -->
<label><input type="radio" ly-model="form.role" value="developer"> Developer</label>
<label><input type="radio" ly-model="form.role" value="designer"> Designer</label>
Full form with validation
Combine ly-model, derived calculations, and ly-on:submit.prevent for accessible, reactive form management.
<div>
<script>
const profile = Lyap.scope('profile');
profile.state({
username: '',
age: 25,
bio: '',
agree: false,
interests: ['coding'],
role: 'developer'
});
profile.derived({
hasErrors: () => !profile.username || profile.age < 18 || !profile.agree
});
profile.actions({
handleSubmit() {
if (this.hasErrors) return;
alert('Saved profile for ' + this.username);
}
});
</script>
<form ly-on:submit.prevent="profile.handleSubmit()">
<label>Username:</label>
<input type="text" ly-model.trim="profile.username">
<label>Age:</label>
<input type="number" ly-model.number="profile.age">
<label>
<input type="checkbox" ly-model="profile.agree"> Agree to terms
</label>
<button type="submit" ly-bind:disabled="profile.hasErrors">Submit Profile</button>
</form>
</div>