Automatic Database Insert
Forms can automatically insert data into your database without writing any controller code. This is perfect for simple use cases like waitlists, newsletter signups, contact forms, and feedback collection.
Basic Usage
<odac:form table="waitlist">
<odac:input name="email" type="email" label="Email">
<odac:validate rule="required|email|unique"/>
</odac:input>
<odac:submit text="Join"/>
</odac:form>
That's it! The form will automatically:
- Validate the email
- Check if it's unique in the database
- Insert the record into
waitlisttable - Show success message
Complete Example
1. Create Database Table
CREATE TABLE `waitlist` (
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
`email` VARCHAR(255) NOT NULL UNIQUE,
`name` VARCHAR(255) NOT NULL,
`created_at` INT UNSIGNED NOT NULL,
`ip` VARCHAR(45) NULL,
`user_agent` TEXT NULL,
INDEX `idx_email` (`email`),
INDEX `idx_created_at` (`created_at`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
2. Create View
view/content/waitlist.html
<div class="waitlist-page">
<h1>Join Our Waitlist</h1>
<odac:form table="waitlist" redirect="/" success="Thank you for joining!">
<odac:input name="email" type="email" label="Email" placeholder="your@email.com">
<odac:validate rule="required|email|unique" message="Please enter a valid email"/>
</odac:input>
<odac:input name="name" type="text" label="Name" placeholder="Your name">
<odac:validate rule="required|minlen:2" message="Name is required"/>
</odac:input>
<odac:set name="created_at" compute="now"/>
<odac:set name="ip" compute="ip"/>
<odac:set name="user_agent" compute="user_agent"/>
<odac:submit text="Join Waitlist" loading="Joining..." class="btn btn-primary"/>
</odac:form>
</div>
3. Create Controller
controller/waitlist.js
module.exports = Odac => {
Odac.View.skeleton('default')
Odac.View.set({content: 'waitlist'})
Odac.View.print()
}
4. Add Route
route/www.js
Odac.Route.page('/waitlist', 'waitlist')
Done! No form submission handler needed.
Form Attributes
table (required)
Database table name where data will be inserted.
<odac:form table="newsletter_subscribers">
redirect (optional)
URL to redirect after successful submission.
<odac:form table="waitlist" redirect="/thank-you">
success (optional)
Custom success message to display.
<odac:form table="waitlist" success="Welcome! We'll notify you soon.">
Unique Validation
Use unique rule to prevent duplicate entries:
<odac:input name="email" type="email">
<odac:validate rule="required|email|unique" message="This email is already registered"/>
</odac:input>
The system will:
- Check if the value exists in the table
- Return error if duplicate found
- Show the custom error message
Auto-Set Values
Use <odac:set> to automatically populate fields:
<odac:set name="created_at" compute="now"/>
<odac:set name="ip" compute="ip"/>
<odac:set name="user_agent" compute="user_agent"/>
<odac:set name="status" value="pending"/>
Compute Types
now- Unix timestamp in secondsdate- Current date (YYYY-MM-DD)datetime- ISO datetime stringtimestamp- Timestamp in millisecondsip- User's IP addressuser_agent- Browser user agentuuid- Generate UUID v4
Static Values
<odac:set name="status" value="pending"/>
<odac:set name="source" value="website"/>
<odac:set name="plan" value="free"/>
Conditional Set
Only set if field is empty:
<odac:set name="country" value="US" if-empty/>
Use Cases
Newsletter Signup
<odac:form table="newsletter" success="Thanks for subscribing!">
<odac:input name="email" type="email">
<odac:validate rule="required|email|unique"/>
</odac:input>
<odac:set name="subscribed_at" compute="now"/>
<odac:set name="status" value="active"/>
<odac:submit text="Subscribe"/>
</odac:form>
Feedback Form
<odac:form table="feedback" redirect="/" success="Thank you for your feedback!">
<odac:input name="rating" type="number" label="Rating (1-5)">
<odac:validate rule="required|min:1|max:5"/>
</odac:input>
<odac:input name="comment" type="textarea" label="Comment">
<odac:validate rule="required|minlen:10"/>
</odac:input>
<odac:set name="created_at" compute="now"/>
<odac:set name="ip" compute="ip"/>
<odac:submit text="Submit Feedback"/>
</odac:form>
Beta Access Request
<odac:form table="beta_requests" success="You're on the list!">
<odac:input name="email" type="email">
<odac:validate rule="required|email|unique"/>
</odac:input>
<odac:input name="company" type="text">
<odac:validate rule="required"/>
</odac:input>
<odac:input name="use_case" type="textarea">
<odac:validate rule="required|minlen:20"/>
</odac:input>
<odac:set name="requested_at" compute="now"/>
<odac:set name="status" value="pending"/>
<odac:submit text="Request Access"/>
</odac:form>
Error Handling
The system automatically handles:
- Validation errors - Shows field-specific error messages
- Duplicate entries - Shows unique constraint errors
- Database errors - Shows generic error message
- Missing database - Shows configuration error
All errors are displayed inline next to the relevant field.
Security
Automatic DB insert includes all security features:
- CSRF token validation
- Session verification
- IP address validation
- User agent verification
- SQL injection prevention (parameterized queries)
- Token expiration (30 minutes)
When to Use
Use automatic DB insert when:
- Simple data collection (waitlist, newsletter, feedback)
- No complex business logic needed
- Direct database insert is sufficient
- You want rapid development
Use custom controller when:
- Need to send emails
- Complex validation logic
- Multiple database operations
- External API calls
- Custom response handling
Combining with Custom Logic
You can add custom logic by specifying a custom action attribute. When you do this, the form data is validated and prepared, but the automatic DB insert is skipped. Instead, your controller receives the validated data via Odac.formData:
// In your view:
// <odac:form action="/contact/submit" table="contacts">
// In your controller:
Odac.Route.post('/contact/submit', async Odac => {
// Odac.formData contains validated form data
// Odac.formConfig contains form configuration
// Perform custom logic (send email, call API, etc.)
await sendEmail(Odac.formData.email, 'Thank you!')
// Manually insert to database if needed
await Odac.DB.contacts.insert(Odac.formData)
return Odac.return({
result: {success: true, message: 'Message sent!'}
})
})
const data = Odac.formData
// Send welcome email
Odac.Mail()
.to(data.email)
.subject('Welcome!')
.send('Thanks for joining!')
// Return custom response
return Odac.return({
result: {
success: true,
message: 'Check your email!'
}
})
})
But for most cases, automatic insert is all you need!