r-model Directive
Connect form controls and writable refs in both directions, with optional conversion modifiers.
The r-model directive provides two-way data binding for form elements in your Regor components. It allows you to bind the value of form inputs to a component's data, ensuring that changes to the input are reflected in the component's data and vice versa.
Connect form controls and writable refs in both directions, with optional conversion modifiers.
Try it live
- Name
- Ada
- Seats
- 3
- Plan
- Team
- Enabled
Controls update state. Resetting state updates the controls.
import { html, ref } from 'regor'
export function createModel(interactive = false) {
const name = ref('Ada')
const seats = ref(3)
const email = ref(true)
const plan = ref('Team')
const reset = () => {
name('Ada')
seats(3)
email(true)
plan('Team')
}
return { interactive, name, seats, email, plan, reset }
}
export const modelTemplate = html` <div class="guide-demo guide-demo--split">
<div class="guide-controls">
<label for="model-name">Name · trim option</label
><input
id="model-name"
type="text"
maxlength="40"
r-model="name, { trim: true }"
:value="name"
:disabled="!interactive"
/>
<label for="model-seats">Seats · .number</label
><input
id="model-seats"
type="range"
min="1"
max="12"
r-model.number="seats"
:value="seats"
:disabled="!interactive"
/>
<label for="model-plan">Plan</label
><select id="model-plan" r-model="plan" :disabled="!interactive">
<option>Solo</option>
<option selected>Team</option>
<option>Studio</option>
</select>
<label class="guide-check"
><input
type="checkbox"
r-model="email"
:checked="email"
:disabled="!interactive"
/>
Email updates</label
><button type="button" @click="reset" :disabled="!interactive">
Reset from state
</button>
</div>
<div class="guide-readout">
<span class="guide-kicker">FORM STATE / TWO WAYS</span>
<dl class="directive-values">
<div>
<dt>Name</dt>
<dd>{{ name || 'Not set' }}</dd>
</div>
<div>
<dt>Seats</dt>
<dd>{{ seats }}</dd>
</div>
<div>
<dt>Plan</dt>
<dd>{{ plan }}</dd>
</div>
<div>
<dt>Email</dt>
<dd>{{ email ? 'Enabled' : 'Disabled' }}</dd>
</div>
</dl>
<p>Controls update state. Resetting state updates the controls.</p>
</div>
</div>` import { createApp, useScope } from 'regor'
import { directiveExamples } from './examples'
const element = document.getElementById('directive-demo')
const name = element?.dataset.example
if (element && name && Object.hasOwn(directiveExamples, name)) {
const example = directiveExamples[name as keyof typeof directiveExamples]
createApp<object>(
useScope<object>(() => example.create(true)),
{ element, template: example.template },
)
} Change the controls, then reset from state. Both directions update the same view.
Syntax
<element r-model="expression"></element> <element>: The form element (e.g., input, textarea, select) that you want to bind to.expression: An expression that represents the data property you want to bind the element to. This can be a single variable or a more complex expression.
Usage
The r-model directive is commonly used with form inputs like text fields, checkboxes, radio buttons, and select elements. It establishes a two-way binding between the input's value and the specified data property in your Regor component.
Example
<div>
<input type="text" r-model="message" />
<p>You typed: {{ message }}</p>
</div> In this example, the r-model directive is used to bind the value of the text input to the message property in your component's data. Any changes made to the input field will automatically update the message property, and vice versa.
Two-Way Data Binding
The r-model directive creates a two-way data binding between the form element and the component's data. This means that changes to either the form element's value or the component's data property are synchronized in real-time.
Supported Form Elements
The r-model directive can be used with various types of form elements:
- Text Input (
<input type="text">) - Textarea (
<textarea>) - Select Dropdown (
<select>) - Checkbox (
<input type="checkbox">) - Radio Button (
<input type="radio">) - Number Input (
<input type="number">and<input type="range">)
Example with Checkbox
<div>
<input type="checkbox" r-model="isChecked" />
<p>Is Checked: {{ isChecked }}</p>
</div> In this example, the r-model directive is used with a checkbox input. The isChecked property in the component's data is bound to the checkbox's checked state. When the checkbox is toggled, the isChecked property will be updated accordingly.
Special Case: Checkbox and Select with Arrays or Sets
When the r-model directive is bound to an array or set in your component's data, it behaves differently for checkboxes and select elements:
Checkbox
If the bound expression is an array or set, the r-model directive will collect the selected values in the array or set. When multiple checkboxes are bound to the same array or set, checking or unchecking the checkboxes will add or remove values from the array or set.
<div>
<input type="checkbox" r-model="selectedItems" value="item1" />
<input type="checkbox" r-model="selectedItems" value="item2" />
<input type="checkbox" r-model="selectedItems" value="item3" />
<p>Selected Items: {{ selectedItems }}</p>
</div> In this example, three checkboxes are bound to the selectedItems array. Checking or unchecking the checkboxes will update the selectedItems array with the selected values.
Select (Dropdown)
Similarly, when the r-model directive is bound to an array or set, and a select element with the multiple attribute is used, it will collect the selected values in the array or set.
<div>
<select r-model="selectedOptions" multiple>
<option value="option1">Option 1</option>
<option value="option2">Option 2</option>
<option value="option3">Option 3</option>
</select>
<p>Selected Options: {{ selectedOptions }}</p>
</div> In this example, the r-model directive is used with a multi-select dropdown. The selectedOptions array will contain the selected values from the dropdown.
Modifiers
The live preview passes the trim option explicitly as a second expression: r-model="name, { trim: true }". This trims the value written to the ref as you type.
The r-model directive supports modifiers to enable additional behavior on the bound element. Modifiers are added to the directive with a dot notation.
Example with Modifiers
<div>
<input type="text" r-model.trim="trimmedMessage" />
<p>Trimmed Message: {{ trimmedMessage }}</p>
</div> The .trim modifier trims the text control when it emits change. The live preview uses the explicit trim option to trim the bound state as you type.
Available Modifiers
.trim: Removes leading and trailing whitespace from the text control onchange. Use the explicittrimoption above to trim the bound value during input..lazy: Updates the component's data property only when the input element emits thechangeevent (useful for input fields that have debounced input events)..number: Converts the input's value to a numeric type (e.g.,Number) before binding it to the data property..int: Converts the input's value to an integer type (e.g.,parseInt) before binding it to the data property.
You can use these modifiers individually or combine them to achieve the desired behavior for your form elements.
Computed values are read-only. Bind r-model to a writable ref, then derive summaries from that state.
Notes
-
The
r-modeldirective is ideal for creating interactive forms and ensuring that user input is synchronized with your component's data. -
For checkboxes and radio buttons, the
r-modeldirective binds thecheckedproperty of the element to the data property, reflecting the boolean state of the checkbox or radio button. -
Changes to the input element's value due to user interactions, such as typing in a text field or selecting options in a dropdown, are automatically reflected in the bound data property.
-
Changes to the data property bound with
r-modelare automatically reflected in the form element's value, allowing you to programmatically update the input's content. -
Modifiers provide additional control over the data binding behavior, allowing you to customize how data is processed and updated between the form element and the component's data.
The r-model directive simplifies the process of creating interactive forms in your Regor-powered applications by enabling two-way data binding between form elements and your component's data properties. It ensures that your forms remain in sync with the underlying data, providing a seamless user experience.