我正在使用Backbone来管理HTML表单的状态。 Model的作用是处理验证。 View的作用是包装HTML表单并响应模型发出的change
或error
事件。
当给定字段实际有效时,Backbone似乎只发出change
个事件。这导致了一些非常意想不到的行为,这让我觉得我做错了。
以下是我正在做的事情的摘要:
1.初始加载序列化表单并将其注入模型
2.当发出error
事件时,我会在无效字段旁边生成错误节点。
3.当发出change
事件时,我会删除(现在有效)字段旁边的错误提示。
当使用最初有效的表单呈现页面,并且用户使字段无效时,将按预期显示该消息;但是,模型从不在内部更新字段。因此,当用户更正错误时,永远不会发出change
事件。
当使用最初的无效表单呈现页面时,事情看起来工作正常......但这只是因为模型的初始属性为空。更正字段会使消息消失,但如果再次将其更改为无效状态,则消息永远不会消失。
我做错了什么?也许我应该使用另一种方法呢?
var Foo = Backbone.Model.extend({
validate: function(attr) {
var errors = {};
if (_.isEmpty(attr)) return;
if (attr.foo && attr.foo != 123) {
errors.foo = ['foo is not equal to 123'];
}
if (attr.bar && attr.bar != 456) {
errors.bar = ['bar is not equal to 456'];
}
return _.isEmpty(errors) ? undefined : errors;
}
});
FooForm = Backbone.View.extend({
events: {
'change :input': 'onFieldChange'
},
initialize: function(options) {
this.model.on('error', this.renderErrors, this);
this.model.on('change', this.updateFields, this);
// Debugging only
this.model.on('all', function() {
console.info('[Foo all]', arguments, this.toJSON())
});
this.model.set(this.serialize());
},
onFieldChange: function(event) {
var field = event.target,
name = field.name,
value = field.value;
this.model.set(name, value);
},
renderErrors: function(model, errors) {
_.each(errors, function(messages, fieldName) {
var el = $('#' + fieldName),
alert = $('<div/>').addClass('error');
el.parent().find('.error').remove();
_.each(messages, function(message) {
alert.clone().text(message).insertAfter(el);
});
});
},
updateFields: function(model, options) {
if (!options || !options.changes) return;
_.each(_.keys(options.changes), function(fieldName) {
var el = $('#' + fieldName);
el.parent().find('.error').remove();
});
},
serialize: function() {
var raw = this.$el.find(':input').serializeArray(),
data = {},
view = this;
$.each(raw, function() {
// Get the model's field name from the form field's name
var name = this.name;
if (data[name] !== undefined) {
if (!data[name].push) {
data[name] = [data[name]];
}
data[name].push(this.value || '');
}
else {
data[name] = this.value || '';
}
});
return data;
}
});
答案 0 :(得分:2)
您无法使用本机Backbone验证来验证单个字段。
在我的应用中,我使用此验证插件:https://github.com/thedersen/backbone.validation
然后在您的模型中为每个字段添加验证规则(它是可选的,因此您无需将其添加到所有模型中):
var NewReview = Backbone.Model.extend({
initialize: function() {
/* ... */
},
validation: {
summary: {
required: true,
minLength: 10
},
pros: {
required: true,
minLength: 10
},
cons: {
required: true,
minLength: 10
},
overall: function(value) {
var text = $(value).text().replace(/\s{2,}/g, ' ');
if (text.length == 0) text = value;
if (text.length < 20) return "Overall review is too short";
},
rating: {
range: [0.5, 5]
},
product_id: {
required: true
}
}
});
在视图或其他地方,您可以验证整个模型或单个字段:
if (this.model.validate()) { ... }
或
if (this.model.isValid("summary")) { ... }