Backbone:逐个验证属性

时间:2012-06-08 06:54:45

标签: backbone.js

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

我有一个型号&一个视图代表整个表单。现在,当我更新属性时:

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

将调用模型上的validate方法。

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

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

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

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

  

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

5 个答案:

答案 0 :(得分:9)

Validate用于使模型保持有效状态,除非您传递silent: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});

答案 1 :(得分:2)

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

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

答案 2 :(得分:1)

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

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

答案 3 :(得分: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 set函数。 通过这种方式,您无需在任何地方通过{silent:true}作为选项 this.model.set('propertyName',val,{silent:true})

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

答案 4 :(得分: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);