Forms & Events
Two-way data binding, form handling, and event management
Form attributes enable interactive forms with two-way data binding, event handling, and error display. These transform static forms into dynamic, data-driven interfaces.
dbind_model
Purpose: Create two-way data binding between form inputs and data. Changes to the input update the data, and changes to the data update the input.
Syntax:
<input dbind_model="fieldName">
<textarea dbind_model="fieldName"></textarea>
<select dbind_model="fieldName"></select>How Two-Way Binding Works
┌─────────────┐ ┌─────────────┐
│ User Input │ ──► │ Data │
│ (typing) │ │ (state) │
└─────────────┘ └──────┬──────┘
▲ │
│ │
└───────────────────┘
Data updates input
- User types in the input
- Data is automatically updated
- Any elements bound to the same data are updated
- If data changes programmatically, the input updates
Supported Input Types
| Input Type | Example |
|---|---|
text | <input type="text" dbind_model="name"> |
email | <input type="email" dbind_model="email"> |
password | <input type="password" dbind_model="password"> |
number | <input type="number" dbind_model="quantity"> |
tel | <input type="tel" dbind_model="phone"> |
url | <input type="url" dbind_model="website"> |
search | <input type="search" dbind_model="query"> |
textarea | <textarea dbind_model="message"></textarea> |
select | <select dbind_model="country">...</select> |
checkbox | <input type="checkbox" dbind_model="agree"> |
radio | <input type="radio" dbind_model="choice"> |
Basic Usage
<!-- Text input -->
<input type="text" dbind_model="username" placeholder="Username">
<!-- Display the bound value -->
<p>Hello, <span dbind_data="username"></span>!</p>As the user types in the input, the greeting updates in real-time.
Text Inputs
<form class="contact-form">
<div class="form-group">
<label for="name">Name</label>
<input type="text" id="name" dbind_model="form.name" required>
</div>
<div class="form-group">
<label for="email">Email</label>
<input type="email" id="email" dbind_model="form.email" required>
</div>
<div class="form-group">
<label for="message">Message</label>
<textarea id="message" dbind_model="form.message" rows="5"></textarea>
</div>
</form>Data:
{
"form": {
"name": "",
"email": "",
"message": ""
}
}Checkbox Binding
For checkboxes, dbind_model binds to a boolean value:
<!-- Single checkbox (boolean) -->
<label>
<input type="checkbox" dbind_model="newsletter">
Subscribe to newsletter
</label>
<!-- The value -->
<span dbind_data="newsletter"></span> <!-- outputs: true or false -->Radio Button Binding
Radio buttons bind to the selected value:
<fieldset>
<legend>Select your plan:</legend>
<label>
<input type="radio" name="plan" value="free" dbind_model="selectedPlan">
Free
</label>
<label>
<input type="radio" name="plan" value="pro" dbind_model="selectedPlan">
Pro ($9/month)
</label>
<label>
<input type="radio" name="plan" value="enterprise" dbind_model="selectedPlan">
Enterprise ($49/month)
</label>
</fieldset>
<p>Selected plan: <span dbind_data="selectedPlan"></span></p>Select Dropdowns
<div class="form-group">
<label for="country">Country</label>
<select id="country" dbind_model="selectedCountry">
<option value="">Select a country</option>
<option value="us">United States</option>
<option value="uk">United Kingdom</option>
<option value="ca">Canada</option>
<option value="au">Australia</option>
</select>
</div>
<p>You selected: <span dbind_data="selectedCountry"></span></p>Dynamic Select Options
Populate select options from data:
<select dbind_model="selectedCategory">
<option value="">Choose a category</option>
<option dbind_repeat="categories" dbind_data="name" value="{{id}}"></option>
</select>Data:
{
"categories": [
{ "id": "tech", "name": "Technology" },
{ "id": "fashion", "name": "Fashion" },
{ "id": "home", "name": "Home & Garden" }
],
"selectedCategory": ""
}Use Cases
1. Live Search Preview
<div class="search-container">
<input type="search" dbind_model="searchQuery" placeholder="Search...">
<div class="search-preview" dbind_show="searchQuery">
Searching for: "<span dbind_data="searchQuery"></span>"
</div>
</div>2. Character Counter
<div class="textarea-container">
<textarea
dbind_model="bio"
maxlength="280"
placeholder="Tell us about yourself..."
></textarea>
<div class="character-count">
<span dbind_data="bio.length">0</span>/280 characters
</div>
</div>3. Live Form Preview
<div class="profile-editor">
<!-- Form -->
<form class="edit-form">
<input type="text" dbind_model="profile.name" placeholder="Name">
<input type="text" dbind_model="profile.title" placeholder="Job Title">
<textarea dbind_model="profile.bio" placeholder="Bio"></textarea>
<input type="url" dbind_model="profile.website" placeholder="Website">
</form>
<!-- Live Preview -->
<div class="preview-card">
<h3 dbind_data="profile.name" dbind_default="Your Name"></h3>
<span class="title" dbind_data="profile.title" dbind_default="Job Title"></span>
<p dbind_data="profile.bio" dbind_default="Your bio goes here..."></p>
<a dbind_href="profile.website" dbind_show="profile.website">Website</a>
</div>
</div>4. Settings Toggle
<div class="settings">
<h2>Notification Settings</h2>
<label class="setting-row">
<input type="checkbox" dbind_model="settings.emailNotifications">
<span>Email notifications</span>
</label>
<label class="setting-row">
<input type="checkbox" dbind_model="settings.pushNotifications">
<span>Push notifications</span>
</label>
<label class="setting-row">
<input type="checkbox" dbind_model="settings.weeklyDigest">
<span>Weekly digest</span>
</label>
<!-- Show summary -->
<div class="settings-summary">
<p dbind_show="settings.emailNotifications">✓ Email notifications enabled</p>
<p dbind_show="settings.pushNotifications">✓ Push notifications enabled</p>
<p dbind_show="settings.weeklyDigest">✓ Weekly digest enabled</p>
</div>
</div>5. Conditional Form Fields
<form class="registration-form">
<select dbind_model="accountType">
<option value="personal">Personal</option>
<option value="business">Business</option>
</select>
<!-- Show only for business accounts -->
<div class="business-fields" dbind_if="accountType==business">
<input type="text" dbind_model="companyName" placeholder="Company Name">
<input type="text" dbind_model="taxId" placeholder="Tax ID">
<input type="text" dbind_model="industry" placeholder="Industry">
</div>
<!-- Show only for personal accounts -->
<div class="personal-fields" dbind_if="accountType==personal">
<input type="date" dbind_model="birthday" placeholder="Birthday">
</div>
</form>dbind_submit
Purpose: Handle form submission and send data to a specified endpoint.
Syntax:
<form dbind_submit="endpoint">
<!-- form fields -->
</form>How It Works
- User submits the form
- DBindly prevents default submission
- Collects all
dbind_modelvalues - Sends data to the specified endpoint
- Handles response (success/error)
Basic Usage
<form dbind_submit="/api/contact">
<input type="text" dbind_model="name" placeholder="Name" required>
<input type="email" dbind_model="email" placeholder="Email" required>
<textarea dbind_model="message" placeholder="Message" required></textarea>
<button type="submit">Send Message</button>
</form>Handling Submission States
<form dbind_submit="/api/newsletter">
<input type="email" dbind_model="email" placeholder="Enter your email" required>
<button type="submit" dbind_hide="isSubmitting">Subscribe</button>
<button type="button" disabled dbind_show="isSubmitting">Sending...</button>
</form>
<!-- Success message -->
<div class="success-message" dbind_show="submitSuccess">
Thank you for subscribing!
</div>
<!-- Error message -->
<div class="error-message" dbind_show="submitError">
Something went wrong. Please try again.
</div>Use Cases
1. Contact Form
<form dbind_submit="/api/contact" class="contact-form">
<div class="form-group">
<label for="contact-name">Name *</label>
<input
type="text"
id="contact-name"
dbind_model="contact.name"
required
>
<span class="error" dbind_error-field="name"></span>
</div>
<div class="form-group">
<label for="contact-email">Email *</label>
<input
type="email"
id="contact-email"
dbind_model="contact.email"
required
>
<span class="error" dbind_error-field="email"></span>
</div>
<div class="form-group">
<label for="contact-subject">Subject</label>
<select id="contact-subject" dbind_model="contact.subject">
<option value="general">General Inquiry</option>
<option value="support">Support</option>
<option value="sales">Sales</option>
</select>
</div>
<div class="form-group">
<label for="contact-message">Message *</label>
<textarea
id="contact-message"
dbind_model="contact.message"
rows="5"
required
></textarea>
<span class="error" dbind_error-field="message"></span>
</div>
<button type="submit" dbind_hide="isSubmitting">
Send Message
</button>
<button type="button" disabled dbind_show="isSubmitting">
Sending...
</button>
</form>
<div class="form-success" dbind_show="submitSuccess">
<h3>Message Sent!</h3>
<p>We'll get back to you within 24 hours.</p>
</div>2. Newsletter Signup
<form dbind_submit="/api/newsletter" class="newsletter-form">
<div class="input-group">
<input
type="email"
dbind_model="newsletter.email"
placeholder="Enter your email"
required
>
<button type="submit" dbind_hide="isSubmitting">Subscribe</button>
</div>
<label class="consent">
<input type="checkbox" dbind_model="newsletter.consent" required>
I agree to receive marketing emails
</label>
<div class="form-messages">
<p class="success" dbind_show="submitSuccess">
Thanks for subscribing! Check your inbox to confirm.
</p>
<p class="error" dbind_error></p>
</div>
</form>3. Feedback Form
<form dbind_submit="/api/feedback" class="feedback-form">
<h3>How was your experience?</h3>
<div class="rating-group" role="radiogroup">
<label>
<input type="radio" name="rating" value="5" dbind_model="feedback.rating">
<span>5 - Excellent</span>
</label>
<label>
<input type="radio" name="rating" value="4" dbind_model="feedback.rating">
<span>4 - Good</span>
</label>
<label>
<input type="radio" name="rating" value="3" dbind_model="feedback.rating">
<span>3 - Average</span>
</label>
<label>
<input type="radio" name="rating" value="2" dbind_model="feedback.rating">
<span>2 - Poor</span>
</label>
<label>
<input type="radio" name="rating" value="1" dbind_model="feedback.rating">
<span>1 - Terrible</span>
</label>
</div>
<div class="form-group">
<label>Any additional comments?</label>
<textarea dbind_model="feedback.comments" rows="3"></textarea>
</div>
<button type="submit">Submit Feedback</button>
</form>dbind_click
Purpose: Handle click events on any element and trigger an action.
Syntax:
<element dbind_click="actionName"></element>
<element dbind_click="actionName:param"></element>Basic Usage
<!-- Simple click action -->
<button dbind_click="increment">+1</button>
<button dbind_click="decrement">-1</button>
<span dbind_data="count">0</span>Click with Parameters
<!-- Pass parameters to the action -->
<button dbind_click="addToCart:{{productId}}">Add to Cart</button>
<button dbind_click="setQuantity:5">Set to 5</button>Use Cases
1. Counter
<div class="counter">
<button dbind_click="decrement" class="btn-minus">−</button>
<span dbind_data="count">0</span>
<button dbind_click="increment" class="btn-plus">+</button>
</div>2. Toggle Visibility
<button dbind_click="toggleDetails">
<span dbind_hide="showDetails">Show Details</span>
<span dbind_show="showDetails">Hide Details</span>
</button>
<div class="details" dbind_show="showDetails">
<p>Here are the details...</p>
</div>3. Tab Navigation
<div class="tabs">
<button dbind_click="setTab:overview" dbind_class="activeTabClass">Overview</button>
<button dbind_click="setTab:features" dbind_class="activeTabClass">Features</button>
<button dbind_click="setTab:specs" dbind_class="activeTabClass">Specs</button>
</div>
<div class="tab-content">
<div dbind_if="activeTab==overview">
<h3>Overview</h3>
<p>Product overview content...</p>
</div>
<div dbind_if="activeTab==features">
<h3>Features</h3>
<ul>
<li>Feature 1</li>
<li>Feature 2</li>
</ul>
</div>
<div dbind_if="activeTab==specs">
<h3>Specifications</h3>
<table>...</table>
</div>
</div>4. Quick Actions
<div class="product-card">
<h3 dbind_data="name"></h3>
<div class="quick-actions">
<button dbind_click="addToCart:{{id}}" title="Add to Cart">🛒</button>
<button dbind_click="addToWishlist:{{id}}" title="Add to Wishlist">❤️</button>
<button dbind_click="quickView:{{id}}" title="Quick View">👁️</button>
</div>
</div>5. Quantity Selector
<div class="quantity-selector">
<button dbind_click="decreaseQuantity" dbind_unless="quantity<=1">−</button>
<input type="number" dbind_model="quantity" min="1" max="99">
<button dbind_click="increaseQuantity" dbind_unless="quantity>=99">+</button>
</div>dbind_error
Purpose: Display general error messages from form submissions or API calls.
Syntax:
<element dbind_error></element>
<element dbind_error="customErrorField"></element>Basic Usage
<form dbind_submit="/api/login">
<input type="email" dbind_model="email" placeholder="Email">
<input type="password" dbind_model="password" placeholder="Password">
<button type="submit">Login</button>
<!-- General error message -->
<div class="error-message" dbind_error>
<!-- Error text appears here -->
</div>
</form>Styling Error Messages
<form dbind_submit="/api/register">
<!-- Form fields -->
<div class="error-container" dbind_show="hasError">
<span class="error-icon">⚠️</span>
<p class="error-text" dbind_error></p>
<button class="dismiss" dbind_click="clearError">×</button>
</div>
</form>CSS:
.error-container {
background: #fef2f2;
border: 1px solid #fecaca;
border-radius: 8px;
padding: 12px;
display: flex;
align-items: center;
gap: 8px;
color: #dc2626;
}dbind_error-field
Purpose: Display field-specific validation error messages.
Syntax:
<element dbind_error-field="fieldName"></element>Basic Usage
<form dbind_submit="/api/register">
<div class="form-group">
<label for="username">Username</label>
<input type="text" id="username" dbind_model="username" required>
<span class="field-error" dbind_error-field="username"></span>
</div>
<div class="form-group">
<label for="email">Email</label>
<input type="email" id="email" dbind_model="email" required>
<span class="field-error" dbind_error-field="email"></span>
</div>
<div class="form-group">
<label for="password">Password</label>
<input type="password" id="password" dbind_model="password" required>
<span class="field-error" dbind_error-field="password"></span>
</div>
<button type="submit">Register</button>
</form>Complete Form with Validation
<form dbind_submit="/api/register" class="registration-form">
<!-- Username -->
<div class="form-group">
<label for="reg-username">Username *</label>
<input
type="text"
id="reg-username"
dbind_model="registration.username"
minlength="3"
maxlength="20"
required
>
<small class="helper-text">3-20 characters, letters and numbers only</small>
<span class="field-error" dbind_error-field="username"></span>
</div>
<!-- Email -->
<div class="form-group">
<label for="reg-email">Email Address *</label>
<input
type="email"
id="reg-email"
dbind_model="registration.email"
required
>
<span class="field-error" dbind_error-field="email"></span>
</div>
<!-- Password -->
<div class="form-group">
<label for="reg-password">Password *</label>
<input
type="password"
id="reg-password"
dbind_model="registration.password"
minlength="8"
required
>
<small class="helper-text">At least 8 characters</small>
<span class="field-error" dbind_error-field="password"></span>
</div>
<!-- Confirm Password -->
<div class="form-group">
<label for="reg-confirm">Confirm Password *</label>
<input
type="password"
id="reg-confirm"
dbind_model="registration.confirmPassword"
required
>
<span class="field-error" dbind_error-field="confirmPassword"></span>
</div>
<!-- Terms -->
<div class="form-group checkbox-group">
<label>
<input type="checkbox" dbind_model="registration.agreeTerms" required>
I agree to the <a href="/terms">Terms of Service</a>
</label>
<span class="field-error" dbind_error-field="agreeTerms"></span>
</div>
<!-- General error -->
<div class="form-error" dbind_error></div>
<!-- Submit -->
<button type="submit" dbind_hide="isSubmitting">Create Account</button>
<button type="button" disabled dbind_show="isSubmitting">Creating...</button>
</form>
<!-- Success message -->
<div class="success-panel" dbind_show="submitSuccess">
<h2>Account Created!</h2>
<p>Please check your email to verify your account.</p>
</div>Server Error Response Format:
{
"error": "Validation failed",
"fields": {
"username": "Username is already taken",
"email": "Please enter a valid email address",
"password": "Password must contain at least one number"
}
}Complete Example: Multi-Step Form
<div class="multi-step-form">
<!-- Progress indicator -->
<div class="progress-steps">
<div class="step" dbind_class="step1Class">
<span class="step-number">1</span>
<span class="step-label">Account</span>
</div>
<div class="step" dbind_class="step2Class">
<span class="step-number">2</span>
<span class="step-label">Profile</span>
</div>
<div class="step" dbind_class="step3Class">
<span class="step-number">3</span>
<span class="step-label">Preferences</span>
</div>
</div>
<!-- Step 1: Account Details -->
<form class="step-content" dbind_if="currentStep==1">
<h2>Account Details</h2>
<div class="form-group">
<label>Email</label>
<input type="email" dbind_model="form.email" required>
<span class="error" dbind_error-field="email"></span>
</div>
<div class="form-group">
<label>Password</label>
<input type="password" dbind_model="form.password" required>
<span class="error" dbind_error-field="password"></span>
</div>
<div class="form-actions">
<button type="button" dbind_click="nextStep">Continue</button>
</div>
</form>
<!-- Step 2: Profile Info -->
<form class="step-content" dbind_if="currentStep==2">
<h2>Profile Information</h2>
<div class="form-row">
<div class="form-group">
<label>First Name</label>
<input type="text" dbind_model="form.firstName" required>
</div>
<div class="form-group">
<label>Last Name</label>
<input type="text" dbind_model="form.lastName" required>
</div>
</div>
<div class="form-group">
<label>Bio</label>
<textarea dbind_model="form.bio" rows="3"></textarea>
</div>
<div class="form-group">
<label>Location</label>
<select dbind_model="form.country">
<option value="">Select country</option>
<option value="us">United States</option>
<option value="uk">United Kingdom</option>
<option value="ca">Canada</option>
</select>
</div>
<div class="form-actions">
<button type="button" dbind_click="prevStep">Back</button>
<button type="button" dbind_click="nextStep">Continue</button>
</div>
</form>
<!-- Step 3: Preferences -->
<form class="step-content" dbind_if="currentStep==3" dbind_submit="/api/register">
<h2>Preferences</h2>
<div class="form-group">
<label>How did you hear about us?</label>
<select dbind_model="form.referralSource">
<option value="">Select one</option>
<option value="google">Google Search</option>
<option value="friend">Friend/Colleague</option>
<option value="social">Social Media</option>
<option value="other">Other</option>
</select>
</div>
<div class="form-group checkbox-group">
<label>
<input type="checkbox" dbind_model="form.newsletter">
Subscribe to our newsletter
</label>
</div>
<div class="form-group checkbox-group">
<label>
<input type="checkbox" dbind_model="form.terms" required>
I agree to the Terms of Service
</label>
<span class="error" dbind_error-field="terms"></span>
</div>
<div class="form-error" dbind_error></div>
<div class="form-actions">
<button type="button" dbind_click="prevStep">Back</button>
<button type="submit" dbind_hide="isSubmitting">Create Account</button>
<button type="button" disabled dbind_show="isSubmitting">Creating...</button>
</div>
</form>
<!-- Success State -->
<div class="success-state" dbind_show="submitSuccess">
<div class="success-icon">✓</div>
<h2>Welcome aboard!</h2>
<p>Your account has been created successfully.</p>
<a href="/dashboard" class="btn-primary">Go to Dashboard</a>
</div>
</div>CSS (excerpt):
.multi-step-form {
max-width: 500px;
margin: 0 auto;
}
.progress-steps {
display: flex;
justify-content: space-between;
margin-bottom: 2rem;
}
.step {
display: flex;
flex-direction: column;
align-items: center;
opacity: 0.5;
}
.step.active {
opacity: 1;
}
.step.completed {
opacity: 1;
color: #22c55e;
}
.step-number {
width: 32px;
height: 32px;
border-radius: 50%;
background: #e5e7eb;
display: flex;
align-items: center;
justify-content: center;
font-weight: bold;
}
.step.active .step-number {
background: #3b82f6;
color: white;
}
.step.completed .step-number {
background: #22c55e;
color: white;
}
.form-actions {
display: flex;
gap: 1rem;
justify-content: flex-end;
margin-top: 2rem;
}Best Practices
1. Always Provide Feedback
<!-- Good: Show loading and success states -->
<form dbind_submit="/api/save">
<button dbind_hide="isSubmitting">Save</button>
<button disabled dbind_show="isSubmitting">Saving...</button>
<span dbind_show="submitSuccess">✓ Saved!</span>
</form>2. Use Field-Level Errors
<!-- Good: Error next to the field -->
<div class="form-group">
<input type="email" dbind_model="email">
<span class="error" dbind_error-field="email"></span>
</div>3. Disable Submit While Processing
<button type="submit" dbind_hide="isSubmitting">Submit</button>
<button type="button" disabled dbind_show="isSubmitting">
<span class="spinner"></span> Processing...
</button>4. Clear Errors on Input
<input
type="email"
dbind_model="email"
onfocus="clearFieldError('email')"
>Next Steps
- Core Binding - Display form data
- Visibility - Conditional form fields
- Formatting - Format form values