10

我需要验证一个包含大量输入的表单。并且,如果输入无效,请在表格中直观地指示特定属性无效。为此,我需要单独验证每个表单元素。

我有一个模型和一个代表整个表单的视图。现在当我更新一个属性时:

this.model.set('name', this.$name.val())

将调用模型上的 validate 方法。

但是,在该方法中,我正在验证所有属性,因此在设置上述属性时,也会验证所有其他属性,如果任何一个属性无效,则会返回错误。这意味着即使我的 'name' 属性有效,我也会得到其他人的错误。

那么,如何只验证一个属性呢?

我认为不可能只通过 validate() 方法验证一个属性。一种解决方案是不使用 validate 方法,而是验证 'change' 事件的每个属性。但这会产生很多变更处理程序。这是正确的方法吗?我还可以做些什么?

我也认为这指出了骨干网中一个更大的问题:

每当您model.set()在模型上设置属性时,都会运行您的验证方法并验证所有属性。这似乎违反直觉,因为您只想验证单个属性。

4

5 回答 5

9

Validatesilent:true用于使您的模型保持有效状态,除非您传递选项,否则它不会让您设置无效值。

您可以一次性设置所有属性:

var M=Backbone.Model.extend({
    defaults:{
        name:"",
        count:0
    },

    validate: function(attrs) {
        var invalid=[];
        if (attrs.name==="") invalid.push("name");
        if (attrs.count===0) invalid.push("count");

        if (invalid.length>0) return invalid;
    }
});

var obj=new M();
obj.on("error",function(model,err) {
    console.log(err);
});
obj.set({
    name:"name",
    count:1
});

或者在设置之前一一验证

var M=Backbone.Model.extend({
    defaults:{
        name:"",
        count:0
    },

    validate: function(attrs) {
        var invalid=[];
        if ( (_.has(attrs,"name"))&&(attrs.name==="") )
            invalid.push("name");
        if ( (_.has(attrs,"count"))&&(attrs.count===0) )
            invalid.push("count");

        if (invalid.length>0) return invalid;
    }
});

var obj=new M();
obj.on("error",function(model,err) {
    console.log(err);
});

if (!obj.validate({name:"name"}))
    obj.set({name:"name"},{silent:true});
于 2012-06-08T08:48:04.687 回答
2

我最近创建了一个小的 Backbone.js 插件Backbone.validateAll,它允许您通过传递validateAll选项仅验证当前正在保存/设置的模型属性。

https://github.com/gfranko/Backbone.validateAll

于 2012-09-04T14:57:28.707 回答
1

这不是 Backbone 的问题,它不会强迫您以某种方式编写验证。验证模型中持久存在的所有属性是没有意义的,因为通常您的模型不包含无效属性,set()如果验证失败,原因不会更改模型,除非您通过静默选项,但这是另一回事。但是,如果您选择这种方式,由于上述要点,验证总是会通过未更改的属性。

您可以自由选择另一种方式:仅验证要设置的属性(作为参数传递给validate())。

于 2012-06-08T08:23:14.967 回答
0

您还可以使用自己的自定义函数重载模型的 set 函数以传递 silent: true 以避免触发验证。

set: function (key, value, options) {
    options || (options = {});
    options = _.extend(options, { silent: true });
    return Backbone.Model.prototype.set.call(this, key, value, options);
}

这基本上在选项中传递 {silent:true} 并使用 {silent: true} 调用 Backbone.Model 设置函数。这样,您就不必在任何地方将 {silent: true} 作为选项传递,您可以调用 this.model.set('propertyName',val, {silent:true})

对于验证,您还可以使用 Backbone.Validation 插件 https://github.com/thedersen/backbone.validation

于 2012-09-20T18:39:53.337 回答
0

我不得不对backbone.validation.js 文件进行修改,但它使这项任务对我来说变得更加容易。我将下面的代码段添加到验证函数中。

validate: function(attrs, setOptions){
            var model = this,
                opt = _.extend({}, options, setOptions);
            if(!attrs){
                return model.validate.call(model, _.extend(getValidatedAttrs(model), model.toJSON()));
            }

            ///////////BEGIN NEW CODE SNIPPET/////////////
            if (typeof attrs === 'string') {
                var attrHolder = attrs;
                attrs = [];
                attrs[attrHolder] = model.get(attrHolder);
            }
            ///////////END NEW CODE SNIPPET///////////////

            var result = validateObject(view, model, model.validation, attrs, opt);
            model._isValid = result.isValid;

            _.defer(function() {
                model.trigger('validated', model._isValid, model, result.invalidAttrs);
                model.trigger('validated:' + (model._isValid ? 'valid' : 'invalid'), model, result.invalidAttrs);
            });

            if (!opt.forceUpdate && result.errorMessages.length > 0) {
                return result.errorMessages;
            }
        }

然后我可以像这样对单个属性调用验证

this.model.set(attributeName, attributeValue, { silent: true });
this.model.validate(attributeName);
于 2013-04-05T17:53:35.927 回答