Backbone Model Validation — Ensuring Data Integrity
In this tutorial, you will learn about Backbone Model Validation. We cover key concepts, practical examples, and best practices to help you master this topic.
Backbone Model validation lets you define rules that check attribute values before saving. The validate method runs automatically during set() (if {validate: true} is passed) and always during save(). Invalid data triggers an invalid event and blocks persistence.
What You'll Learn
You'll learn how to define validation rules, trigger validation on set and save, handle validation errors, use custom error messages, and create reusable validation patterns.
Why It Matters
Validating data on the client prevents bad data from reaching the server, reduces network requests, and gives users immediate feedback. Security tools should validate input before analysis to avoid processing malformed data.
Real-World Use
A malware analysis platform validates file hash format before submitting to the scanning engine. If the hash is not a valid SHA256 string (64 hex characters), the Model refuses to save and shows an error instantly.
flowchart LR
A[User input] --> B[set or save]
B --> C[validate method]
C --> D{Valid?}
D -->|Yes| E[Update attributes]
D -->|No| F[invalid event]
F --> G[error callback]
G --> H[Show error message]
E --> I[save to server]
Basic Validation
Define a validate method that returns an error string if validation fails. If it returns nothing, validation passes.
var Task = Backbone.Model.extend({
defaults: {
title: '',
priority: 'medium'
},
validate: function(attrs) {
if (!attrs.title || attrs.title.trim() === '') {
return 'Title cannot be empty';
}
if (attrs.title.length > 200) {
return 'Title must be under 200 characters';
}
}
});
var task = new Task();
task.on('invalid', function(model, error) {
console.log('Validation error:', error);
});
// Trigger validation manually
task.set({ title: '' }, { validate: true });
console.log('After invalid set:', task.get('title'));
Expected output:
Validation error: Title cannot be empty
After invalid set: (default empty string)
Validation on Save
save() always runs validation before sending data to the server. If validation fails, the error callback fires.
var User = Backbone.Model.extend({
urlRoot: '/api/users',
validate: function(attrs) {
if (!attrs.email) {
return 'Email is required';
}
if (attrs.email.indexOf('@') === -1) {
return 'Email must contain @';
}
if (!attrs.password || attrs.password.length < 6) {
return 'Password must be at least 6 characters';
}
}
});
var user = new User({ email: 'invalid', password: '123' });
user.save(null, {
error: function(model, response) {
// response is the validation error string
console.log('Save failed:', response);
}
});
Expected output:
Save failed: Email must contain @
Multiple Field Validation
Validate combinations of fields together. A common pattern is checking that two fields match.
var Registration = Backbone.Model.extend({
defaults: {
username: '',
password: '',
confirmPassword: ''
},
validate: function(attrs) {
var errors = [];
if (!attrs.username || attrs.username.length < 3) {
errors.push('Username must be at least 3 characters');
}
if (!attrs.password || attrs.password.length < 8) {
errors.push('Password must be at least 8 characters');
}
if (attrs.password !== attrs.confirmPassword) {
errors.push('Passwords do not match');
}
if (errors.length > 0) {
return errors.join(', ');
}
}
});
var reg = new Registration({
username: 'ab',
password: '12345',
confirmPassword: 'different'
});
reg.on('invalid', function(model, error) {
console.log('Errors:', error);
});
reg.save(null, { error: function(m, e) { console.log('Blocked:', e); } });
Expected output:
Errors: Username must be at least 3 characters, Password must be at least 8 characters, Passwords do not match
Blocked: Username must be at least 3 characters, Password must be at least 8 characters, Passwords do not match
Async Validation with Server Check
Backbone's built-in validation is synchronous. For async validation (e.g., checking if a username is taken), run validation before calling save manually.
var SignupForm = Backbone.Model.extend({
defaults: {
username: '',
email: ''
},
validate: function(attrs) {
if (!attrs.username) return 'Username required';
if (!attrs.email) return 'Email required';
}
});
var form = new SignupForm({ username: 'newuser', email: 'test@test.com' });
// Simulate async server check
function checkUsername(username) {
return $.Deferred().resolve({ available: true });
}
form.on('invalid', function(m, e) { console.log('Error:', e); });
checkUsername(form.get('username')).done(function(result) {
if (!result.available) {
console.log('Username taken — show error');
} else {
form.save(null, {
success: function() { console.log('Registered!'); },
error: function(m, e) { console.log('Save error:', e); }
});
}
});
Expected output:
Username taken — show error
Conditional Validation
Apply rules based on other attribute values. Different states may require different validation.
var Order = Backbone.Model.extend({
defaults: {
type: 'standard',
shippingAddress: '',
expressFee: 0
},
validate: function(attrs) {
if (!attrs.shippingAddress) {
return 'Shipping address is required';
}
// Express orders require a phone number
if (attrs.type === 'express' && !attrs.phone) {
return 'Phone number required for express shipping';
}
if (attrs.type === 'international' && !attrs.customsInfo) {
return 'Customs info required for international orders';
}
}
});
var order = new Order({ type: 'express', shippingAddress: '123 Main St' });
order.on('invalid', function(m, e) { console.log(e); });
order.save(null, { error: function(m, e) { console.log(e); } });
order.set({ phone: '555-0100' }, { validate: true });
console.log('Order valid now:', order.isValid());
Expected output:
Phone number required for express shipping
Order valid now: true
Using isValid
The isValid() method runs validation without triggering events or blocking save. Use it to check state before showing forms.
var Task = Backbone.Model.extend({
defaults: { title: '', priority: '' },
validate: function(attrs) {
if (!attrs.title) return 'Title required';
if (!attrs.priority) return 'Priority required';
}
});
var task = new Task({ title: 'Test' });
console.log('Valid without priority:', task.isValid());
task.set('priority', 'high');
console.log('Valid with priority:', task.isValid());
Expected output:
Valid without priority: false
Valid with priority: true
Common Mistakes
- Not passing
{validate: true}toset(). By default,set()does NOT run validation. Onlysave()always validates. Useset({...}, {validate: true})to validate on set. - Returning a string instead of nothing on success. If
validatereturns any truthy value, Backbone treats it as an error. Returnundefinedor nothing when valid. - Using alert() in validation. Validation errors should be returned as strings, not shown with alert(). Let the View handle display.
- Not listening to the
invalidevent. If no one listens forinvalid, validation errors are silently swallowed. Always attach aninvalidhandler. - Relying only on client-side validation. Server-side validation is mandatory. Client-side validation is for UX, not security.
Practice Questions
- How do you trigger validation when calling
set()? - What does the
validatemethod need to return to indicate success? - How do you check if a Model is currently valid without triggering events?
- What happens if
save()is called and validation fails? - Challenge: Create a
PasswordResetModel with validation rules: password must be 8+ chars, contain a number and special character, and match confirmPassword. Test all three error cases.
FAQ
Mini Project
Create a ServerConfig Model that validates: hostname is required and matches a regex, port is between 1 and 65535, protocol is http or https, and timeout is a positive number. Test all validation rules. Attach an invalid handler that logs each error.
What's Next
Now that you can validate Models, learn Backbone Collections for managing groups of Models. Then explore Backbone Collection Methods for filtering, sorting, and querying data.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro