我在使用backbone.js应用程序时遇到了麻烦,我正在努力学习。我为它设置了jsfiddle。
这是JavaScript:
var app = {};
$(document).ready(function() {
app.Contact = Backbone.Model.extend({
defaults: {
firstName: '',
lastName: '',
email: ''
},
validate: function(attrs) {
var errors = [];
if (attrs.firstName.trim() == "") {
errors.push({
'message': 'Please enter a first name.',
'field': 'firstName'
});
}
if (attrs.lastName.trim() == "") {
errors.push({
'message': 'Please enter a last name.',
'field': 'lastName'
});
}
if (attrs.email.trim() == "") {
errors.push({
'message': 'Please enter an email address.',
'field': 'email'
});
}
if (errors.length) {
return errors;
} else {
return false;
}
}
});
app.ContactList = Backbone.Collection.extend({
model: app.Contact,
localStorage: new Store('backbone-addressbook')
});
app.contactList = new app.ContactList();
app.ContactView = Backbone.View.extend({
tagName: 'tr',
template: _.template($('#contact-template').html()),
render: function() {
this.$el.html(this.template(this.model.toJSON()));
return this;
},
initialize: function() {
this.model.on('change', this.render, this);
this.model.on('destroy', this.remove, this);
var self = this;
this.model.on('invalid', function(model, errors) {
_.each(errors, function(error, i) {
console.log(self.el);
$(self.el).find('[data-field="' + error.field + '"]').parent().addClass('has-error');
$(self.el).find('[data-field="' + error.field + '"]').parent().find('.help-block').remove();
$(self.el).find('[data-field="' + error.field + '"]').parent().append('<span class="help-block">' + error.message + '</span>');
});
});
this.model.on('change', function(model, response) {
//console.log(self.el);
$(self.el).removeClass('editing');
this.render;
})
},
events: {
'dblclick label': 'edit',
'keypress .edit': 'updateOnEnter',
'click .destroy': 'destroy',
'click .save': 'close'
},
edit: function(e) {
this.$el.addClass('editing');
$(e.currentTarget).next('input').focus();
},
updateOnEnter: function(e) {
if (e.which == 13) {
this.close(e);
}
},
close: function(e) {
e.preventDefault();
var updateObject = {};
$(this.el).find('input[type="text"]').each(function() {
node = $(this);
updateObject[node.data('field')] = node.val();
});
this.model.save(updateObject, {validate: true});
},
destroy: function() {
this.model.destroy();
}
});
app.AppView = Backbone.View.extend({
el: '#newContact',
initialize: function() {
$(this).find('.has-error').removeClass('has-error');
$(this).remove('.help-block');
app.contactList.on('add', this.addOne, this);
app.contactList.fetch();
var self = this;
app.contactList.on('invalid', function(model, errors) {
_.each(errors, function(error, i) {
console.log(self.el);
$(self.el).find('[data-field="' + error.field + '"]').parent().addClass('has-error');
$(self.el).find('[data-field="' + error.field + '"]').parent().find('.help-block').remove();
$(self.el).find('[data-field="' + error.field + '"]').parent().append('<span class="help-block">' + error.message + '</span>');
});
});
},
events: {
'click .add': 'createContact'
},
createContact: function(e) {
e.preventDefault();
app.contactList.create(this.newAttributes(), {validate: true});
},
addOne: function(contact) {
var view = new app.ContactView({model: contact});
$('#contactList').append(view.render().el);
$('form input[type="text"]').val('');
$('form input[type="text"]').parent().removeClass('has-error');
$('.help-block').remove();
},
newAttributes: function() {
var updateObject = {};
$(this.el).find('input[type="text"]').each(function() {
node = $(this);
updateObject[node.data('field')] = node.val();
});
return updateObject;
},
});
app.appView = new app.AppView();
});
这是HTML:
<div class="container">
<section id="addressbookapp">
<header id="header">
<h1>Address Book</h1>
<div class="well">
<form id="newContact" action="#" role="form">
<div class="form-group">
<label class="control-label" for="firstName">First Name</label>
<input data-field="firstName" class="newFirstName form-control input-sm" type="text" />
</div>
<div class="form-group">
<label class="control-label" for="lastName">Last Name</label>
<input data-field="lastName" class="newLastName form-control input-sm" type="text" />
</div>
<div class="form-group">
<label class="control-label" for="email">Email Address</label>
<input data-field="email" class="newEmail form-control input-sm" type="text" />
</div>
<button class="add btn-xs">Add</button>
</form>
</div>
</header>
<section id="main">
<table class="table table-striped">
<caption>Double-click to edit an entry.</caption>
<thead>
<tr>
<th>First</th>
<th>Last</th>
<th>Email</th>
<th></th>
</tr>
</thead>
<tbody id="contactList"></tbody>
</table>
</section>
</section>
</div>
<script id="contact-template" type="text/template">
<form action="#" role="form">
<td>
<label class="control-label" for="firstName"><%- firstName %></label>
<input data-field="firstName" class="firstName input-sm edit" value="<%- firstName %>" type="text" />
</td>
<td>
<label class="control-label" for="lastName"><%- lastName %></label>
<input data-field="lastName" class="lastName input-sm edit" value="<%- lastName %>" type="text" />
</td>
<td>
<label class="control-label" for="email"><%- email %></label>
<input data-field="email" class="email input-sm edit" value="<%- email %>" type="email" />
</td>
<td>
<button class="btn-xs save">Save</button>
<button class="btn-xs destroy">Delete</button>
</td>
</form>
</script>
具体来说,当用户编辑列表中的条目(通过双击)时,清除输入(例如,姓氏),然后尝试保存,(正确)验证错误。问题是顶部的表单(用于创建新条目)也响应无效事件。
我的问题不仅仅是如何防止这种情况发生,而是组织事物的理想方式。这对我来说是一次学习练习,所以我要感谢任何提示 - 你看到的任何可以改进的地方。
答案 0 :(得分:1)
这是由于您构建应用程序的方式:在&#34; new&#34;和&#34;编辑&#34;表单,您告诉应用程序如果集合中存在验证问题,则显示错误消息&#34;。因此,当您尝试编辑现有模型并且存在验证问题时,&#34; new&#34;表单更新以显示错误。
您需要做的是在&#34; new&#34;中使用新的(空白)模型。表单,如果没有验证则显示错误,如果它有效则将其添加到集合中。这样,两种形式的错误都由不同的机制处理,并且不会重叠。
请参阅http://jsfiddle.net/n9yq2/3/
app.AppView = Backbone.View.extend({
el: '#newContact',
initialize: function() {
this.model = new app.Contact();
// edited for brevity
this.model.on('invalid', function(model, errors) {
_.each(errors, function(error, i) {
createContact: function(e) {
e.preventDefault();
var attrs = this.newAttributes();
if(this.model.set(attrs, {validate: true})){
app.contactList.create(attrs);
}
},