Odac Register Forms
The <odac:register> component provides a zero-configuration way to create secure registration forms. Simply write HTML, and Odac handles validation, security, database operations, and auto-login automatically.
Quick Start
1. Configure Database (odac.json)
{
"mysql": {
"host": "localhost",
"user": "root",
"password": "",
"database": "your_database"
}
}
That's all you need! The auth configuration is optional.
2. Create Your Form (view/content/register.html)
<odac:register redirect="/dashboard">
<odac:input name="email" type="email" placeholder="Email" unique>
<odac:validate rule="required|email" message="Please enter a valid email"/>
</odac:input>
<odac:input name="username" type="text" placeholder="Username" unique>
<odac:validate rule="required|minlen:4" message="Username must be at least 4 characters"/>
</odac:input>
<odac:input name="password" type="password" placeholder="Password">
<odac:validate rule="required|minlen:8" message="Password must be at least 8 characters"/>
</odac:input>
<odac:submit>Create Account</odac:submit>
</odac:register>
That's it! No JavaScript, no controller code, no SQL needed. The form automatically:
- Creates the database table (if it doesn't exist)
- Validates input (client-side and server-side)
- Checks for unique email/username
- Hashes passwords with bcrypt
- Creates the user account
- Logs in the user
- Redirects to dashboard
3. Optional: Customize Auth Configuration
If you want to customize table names or primary key:
{
"mysql": {
"host": "localhost",
"user": "root",
"password": "",
"database": "your_database"
},
"auth": {
"table": "users", // Optional: User table name (default: "users")
"key": "id", // Optional: Primary key (default: "id")
"token": "candy_auth" // Optional: Token table (default: "candy_auth")
}
}
If you don't specify auth config:
- Table name defaults to
users - Primary key defaults to
id - Token table defaults to
candy_auth - Table is created automatically based on your form fields
Form Attributes
<odac:register>
Main form container with configuration options:
<odac:register
redirect="/dashboard" <!-- Redirect URL after successful registration -->
autologin="true"> <!-- Auto-login after registration (default: true) -->
<!-- fields here -->
</odac:register>
Attributes:
redirect- URL to redirect after successful registrationautologin- Whether to automatically log in the user (default:true)
Field Types
<odac:input>
Defines an input field with validation rules:
<odac:input
name="email" <!-- Field name (required) -->
type="email" <!-- Input type (default: text) -->
placeholder="Email" <!-- Placeholder text -->
label="Email Address" <!-- Label text (optional) -->
unique> <!-- Check uniqueness in database -->
<odac:validate rule="required|email" message="Valid email required"/>
</odac:input>
Attributes:
name- Field name (required)type- Input type: text, email, password, number, checkbox, textareaplaceholder- Placeholder textlabel- Label text (for checkbox or explicit labels)unique- Check if value already exists in databaseskip- Validate field but don't save to database (useful for password confirmation, terms acceptance)
Supported Input Types:
text- Text inputemail- Email input (with HTML5 validation)password- Password inputnumber- Number inputcheckbox- Checkbox inputtextarea- Textarea
Skip Attribute
Use the skip attribute for fields that should be validated but not saved to the database:
<!-- Password confirmation - validate but don't save -->
<odac:input name="confirm_password" type="password" placeholder="Confirm Password" skip>
<odac:validate rule="required|same:password" message="Passwords must match"/>
</odac:input>
<!-- Terms acceptance - validate but don't save -->
<odac:input name="terms" type="checkbox" label="I accept the terms" skip>
<odac:validate rule="accepted" message="You must accept the terms"/>
</odac:input>
<!-- Captcha verification - validate but don't save -->
<odac:input name="captcha" type="text" placeholder="Enter captcha" skip>
<odac:validate rule="required" message="Please complete the captcha"/>
</odac:input>
Common Use Cases:
- Password confirmation fields
- Terms and conditions checkboxes
- Privacy policy acceptance
- Captcha verification
- Temporary validation fields
Validation Rules
<odac:validate>
Defines validation rules for a field:
<odac:validate
rule="required|minlen:4|alphanumeric"
message="Username must be 4+ alphanumeric characters"/>
Attributes:
rule- Validation rules (pipe-separated)message- Error message to display
Available Rules
Basic Rules:
required- Field is requiredemail- Valid email formaturl- Valid URL formatnumeric- Only numbersalpha- Only lettersalphanumeric- Letters and numbers onlyalphaspace- Letters and spaces onlyalphanumericspace- Letters, numbers, and spacesaccepted- Must be accepted (for checkboxes)
Length Rules:
minlen:X- Minimum lengthmaxlen:X- Maximum lengthlen:X- Exact length
Number Rules:
min:X- Minimum valuemax:X- Maximum value
Comparison Rules:
same:field- Must match another fielddifferent:field- Must be different from another fieldequal:value- Must equal specific valuenot:value- Must not equal specific value
Pattern Rules:
regex:pattern- Custom regex patterndomain- Valid domain nameip- Valid IP addressmac- Valid MAC address
Special Rules:
unique- Check uniqueness in database (use withuniqueattribute on field)xss- Check for XSS attempts
Multiple Validation Rules
You can add multiple <odac:validate> tags for different error messages:
<odac:input name="username" type="text" unique>
<odac:validate rule="required" message="Username is required"/>
<odac:validate rule="minlen:4" message="Username must be at least {min} characters"/>
<odac:validate rule="maxlen:20" message="Username cannot exceed {max} characters"/>
<odac:validate rule="alphanumeric" message="Username can only contain letters and numbers"/>
<odac:validate rule="unique" message="Username '{value}' is already taken"/>
</odac:input>
Or combine rules in a single tag:
<odac:input name="username" type="text" unique>
<odac:validate
rule="required|minlen:4|maxlen:20|alphanumeric"
message="Username must be 4-20 alphanumeric characters"/>
<odac:validate rule="unique" message="Username '{value}' is already taken"/>
</odac:input>
Message Placeholders
Use placeholders in error messages for dynamic values:
<odac:input name="username" type="text">
<odac:validate
rule="minlen:4"
message="Username '{value}' is too short. Minimum {min} characters required"/>
</odac:input>
<odac:input name="age" type="number">
<odac:validate
rule="min:18|max:120"
message="Age must be between {min} and {max} years"/>
</odac:input>
Available Placeholders:
{value}- User's input value{field}- Field name{label}- Field label or placeholder{min}- Minimum value (for minlen, min rules){max}- Maximum value (for maxlen, max rules){len}- Required length (for len rule){other}- Other field name (for same, different rules)
Backend-Only Values
<odac:set>
Set values that are processed only on the backend (not visible in HTML):
<odac:register redirect="/dashboard">
<!-- User input fields -->
<odac:input name="email" type="email" unique>
<odac:validate rule="required|email"/>
</odac:input>
<!-- Backend-only values -->
<odac:set name="role" value="user"/>
<odac:set name="status" value="pending"/>
<odac:set name="registered_at" compute="now"/>
<odac:set name="ip_address" compute="ip"/>
<odac:submit>Register</odac:submit>
</odac:register>
Attributes:
name- Field name (required)value- Static valuecompute- Computed value (see below)callback- Custom callback functionif-empty- Only set if user didn't provide a value
Computed Values
Use compute attribute for dynamic values:
<odac:set name="registered_at" compute="now"/> <!-- Unix timestamp -->
<odac:set name="date" compute="date"/> <!-- 2025-01-20 -->
<odac:set name="datetime" compute="datetime"/> <!-- ISO 8601 -->
<odac:set name="timestamp" compute="timestamp"/> <!-- Milliseconds -->
<odac:set name="ip_address" compute="ip"/> <!-- User's IP -->
<odac:set name="user_agent" compute="user_agent"/> <!-- Browser info -->
<odac:set name="uuid" compute="uuid"/> <!-- UUID v4 -->
Conditional Values
Use if-empty to set a default only if the user didn't provide a value:
<odac:input name="country" type="text" placeholder="Country (optional)">
<!-- User can optionally fill this -->
</odac:input>
<odac:set name="country" value="TR" if-empty/>
<!-- If user leaves it empty, set to "TR" -->
Submit Button
<odac:submit>
Defines the submit button:
<odac:submit
text="Create Account" <!-- Button text -->
loading="Creating account..."> <!-- Loading state text -->
</odac:submit>
Or use content as button text:
<odac:submit>Create Account</odac:submit>
Complete Example
<odac:register redirect="/dashboard" autologin="true">
<!-- Email Field -->
<odac:input name="email" type="email" placeholder="Email Address" unique>
<odac:validate rule="required" message="Email is required"/>
<odac:validate rule="email" message="Please enter a valid email address"/>
<odac:validate rule="unique" message="The email '{value}' is already registered"/>
</odac:input>
<!-- Username Field -->
<odac:input name="username" type="text" placeholder="Username" unique>
<odac:validate rule="required" message="Username is required"/>
<odac:validate rule="minlen:4" message="Username must be at least {min} characters"/>
<odac:validate rule="maxlen:20" message="Username cannot exceed {max} characters"/>
<odac:validate rule="alphanumeric" message="Only letters and numbers allowed"/>
<odac:validate rule="unique" message="Username '{value}' is already taken"/>
</odac:input>
<!-- Password Field -->
<odac:input name="password" type="password" placeholder="Password">
<odac:validate rule="required" message="Password is required"/>
<odac:validate rule="minlen:8" message="Password must be at least {min} characters"/>
</odac:input>
<!-- Password Confirmation -->
<odac:input name="password_confirm" type="password" placeholder="Confirm Password" skip>
<odac:validate rule="required" message="Please confirm your password"/>
<odac:validate rule="same:password" message="Passwords do not match"/>
</odac:input>
<!-- Full Name -->
<odac:input name="name" type="text" placeholder="Full Name">
<odac:validate rule="required" message="Name is required"/>
<odac:validate rule="alphaspace" message="Name can only contain letters and spaces"/>
<odac:validate rule="minlen:3" message="Name must be at least {min} characters"/>
</odac:input>
<!-- Age -->
<odac:input name="age" type="number" placeholder="Age">
<odac:validate rule="required" message="Age is required"/>
<odac:validate rule="min:18" message="You must be at least {min} years old"/>
<odac:validate rule="max:120" message="Please enter a valid age"/>
</odac:input>
<!-- Terms Checkbox -->
<odac:input name="terms" type="checkbox" label="I agree to the terms and conditions" skip>
<odac:validate rule="accepted" message="You must accept the terms to continue"/>
</odac:input>
<!-- Backend-only values -->
<odac:set name="role" value="user"/>
<odac:set name="status" value="active"/>
<odac:set name="registered_at" compute="now"/>
<odac:set name="ip_address" compute="ip"/>
<odac:set name="user_agent" compute="user_agent"/>
<!-- Submit Button -->
<odac:submit text="Create Account" loading="Creating your account..."/>
</odac:register>
Security Features
Automatic Security
Odac automatically handles:
- CSRF Protection - Form tokens prevent cross-site attacks
- Password Hashing - Passwords are hashed with bcrypt
- SQL Injection Prevention - All queries are parameterized
- XSS Protection - Input is sanitized
- Field Whitelisting - Only defined fields are processed
- Token Expiration - Form tokens expire after 30 minutes
Token System
Each form gets a unique token when rendered:
- Token is stored server-side with field whitelist
- Token expires after 30 minutes
- Only fields defined in the view are accepted
- Backend-only values (
<odac:set>) are never exposed to HTML
Unique Field Checking
Fields marked with unique attribute are checked against the database:
<odac:input name="email" type="email" unique>
<odac:validate rule="unique" message="Email already exists"/>
</odac:input>
The system automatically queries the auth table to check for duplicates.
HTML5 Validation
Odac automatically adds HTML5 validation attributes for better UX:
<!-- This field -->
<odac:input name="username" type="text">
<odac:validate rule="required|minlen:4|maxlen:20|alphanumeric"/>
</odac:input>
<!-- Generates this HTML -->
<input
type="text"
name="username"
required
minlength="4"
maxlength="20"
pattern="[a-zA-Z0-9]+">
Automatic HTML5 Attributes:
required- For required fieldsminlength/maxlength- For length validationmin/max- For number validationpattern- For alphanumeric, numeric, alpha rulestype="email"- Native email validationtype="url"- Native URL validation
This provides instant feedback to users before form submission.
Configuration Reference
Required Configuration
Only MySQL configuration is required:
{
"mysql": {
"host": "localhost",
"user": "root",
"password": "",
"database": "your_database"
}
}
Optional Auth Configuration
Customize table names and primary key if needed:
{
"auth": {
"table": "users", // User table name (default: "users")
"key": "id", // Primary key column (default: "id")
"token": "candy_auth" // Session token table (default: "candy_auth")
}
}
Default Values:
- If
authis not specified, defaults are used - Table:
users - Primary key:
id - Token table:
candy_auth - All tables are created automatically if they don't exist
Database Schema
Auto-Creation (Recommended):
The users table is created automatically on first registration! Odac analyzes your form fields and creates the appropriate table structure:
- Fields with
uniqueattribute →VARCHAR(255) NOT NULL UNIQUE - Password field →
VARCHAR(255) NOT NULL(for bcrypt hashes) - Number fields →
INTorBIGINT - Text fields →
VARCHAR(255)orTEXT(if > 255 chars) - Boolean fields →
TINYINT(1) - Timestamps →
created_atandupdated_atadded automatically
Manual Creation (Optional):
If you prefer to create the table manually:
CREATE TABLE `users` (
`id` INT NOT NULL AUTO_INCREMENT,
`email` VARCHAR(255) NOT NULL UNIQUE,
`username` VARCHAR(255) NOT NULL UNIQUE,
`password` VARCHAR(255) NOT NULL,
`name` VARCHAR(255) NULL,
`role` VARCHAR(50) DEFAULT 'user',
`status` VARCHAR(50) DEFAULT 'active',
`registered_at` INT NULL,
`ip_address` VARCHAR(45) NULL,
`user_agent` TEXT NULL,
`created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
`updated_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
Important:
- Password field must be
VARCHAR(255)to store bcrypt hashes (60 chars + future-proofing) - Fields marked with
uniqueattribute should haveUNIQUEconstraint - Auto-creation uses
utf8mb4_unicode_cicollation for full Unicode support
Token Table
The token table is created automatically on first login, but you can create it manually:
CREATE TABLE `candy_auth` (
`id` INT NOT NULL AUTO_INCREMENT,
`user` INT NOT NULL,
`token_x` VARCHAR(255) NOT NULL,
`token_y` VARCHAR(255) NOT NULL,
`browser` VARCHAR(255) NOT NULL,
`ip` VARCHAR(255) NOT NULL,
`date` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
`active` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
Error Handling
Display Errors
Error messages are automatically displayed in <span> elements with odac-form-error attribute:
<!-- Errors appear here automatically -->
<span class="odac-form-error" odac-form-error="email" style="display:none;"></span>
Success Messages
Success messages appear in elements with odac-form-success class:
<!-- Success message appears here -->
<span class="odac-form-success" style="display:none;"></span>
Custom Styling
Style error and success messages with CSS:
.odac-form-error {
color: red;
font-size: 0.875rem;
margin-top: 0.25rem;
}
.odac-form-success {
color: green;
font-size: 1rem;
padding: 1rem;
background: #d4edda;
border: 1px solid #c3e6cb;
border-radius: 0.25rem;
}
.odac-field {
margin-bottom: 1rem;
}
input._odac_error {
border-color: red;
}
Advanced Usage
Custom Callbacks
You can define custom callbacks for computed values:
// In your page controller or global script
Odac.fn.generateReferralCode = async (Odac) => {
return Math.random().toString(36).substring(2, 10).toUpperCase()
}
<odac:set name="referral_code" callback="generateReferralCode"/>
Conditional Registration
Disable auto-login and handle redirect manually:
<odac:register autologin="false">
<!-- fields -->
</odac:register>
Then handle the response in JavaScript if needed (though not required for basic usage).
Best Practices
- Always validate on both client and server - Odac does this automatically
- Use unique attribute for email/username - Prevents duplicate accounts
- Set minimum password length - Use
minlen:8or higher - Use password confirmation - Add a
password_confirmfield withsame:passwordrule - Add terms checkbox - Use
acceptedrule for legal compliance - Use backend-only values - Store metadata with
<odac:set> - Provide clear error messages - Use placeholders for dynamic values
- Test form expiration - Forms expire after 30 minutes
Troubleshooting
Form Not Submitting
- Check that
odac.jsonhas auth configuration - Verify database table exists
- Check browser console for JavaScript errors
Validation Not Working
- Ensure validation rules are spelled correctly
- Check that field names match between
<odac:input>and validation - Verify HTML5 validation isn't blocking submission
Unique Check Failing
- Verify
uniqueattribute is on the field - Check that auth table name in config matches your database
- Ensure the field exists in your database table
Token Expired
- Forms expire after 30 minutes
- User needs to refresh the page to get a new token
- Consider adding a message about session expiration