主干集合添加不会触发模型验证

时间:2013-06-23 19:09:32

标签: validation backbone.js collections add

我是骨干新手,想要测试处理待办事项列表的简单脚本。这是我到目前为止使用的代码:

(function() {

    window.App = {
        Models: {},
        Collections: {},
        Views: {}
    };

    window.template = function(id) {
        return _.template($('#' + id).html());
    }

    App.Models.Task = Backbone.Model.extend({
        validate: function(attributes) {
            if ( !$.trim(attributes.title) ) {
                return 'Invalid title';
            }
        }
    });
    App.Collections.Tasks = Backbone.Collection.extend({
        model: App.Models.Task
    });
    App.Views.Task = Backbone.View.extend({
        tagName: 'li',
        template: template('taskTemplate'),
        initialize: function () {
            this.model.on('change', this.render, this);
            this.model.on('destroy', this.remove, this);
        },
        events: {
            'click .edit': 'editTask',
            'click .delete': 'destroy'
        },
        destroy: function() {
            if (confirm('Are you sure?')) {
                this.model.destroy();
            }
        },
        remove: function() {
            this.$el.remove();
        },
        editTask: function() {
            var newTaskTitle = prompt('New title:', this.model.get('title'));
            this.model.set('title', newTaskTitle, {validate: true});
        },
        render: function() {
            this.$el.html(this.template(this.model.toJSON()));
            return this;
        }
    });
    App.Views.AddTask = Backbone.View.extend({
        el: 'form#addTask',
        initialize: function() {

        },
        events: {
            'submit': 'submit'
        },
        submit: function(event) {
            event.preventDefault();
            var newTaskTitle = $(event.currentTarget).find('input[type=text]').val();
            var task = new App.Models.Task({ title: newTaskTitle });
            this.collection.add(task, {add: true, merge: false, remove: false});
        }
    });
    App.Views.Tasks = Backbone.View.extend({
        tagName: 'ul',
        initialize: function() {
            this.collection.on('add', this.addOne, this);
        },
        render: function() {
            this.collection.each(this.addOne, this);
            return this;
        },
        addOne: function(task) {
            var taskView = new App.Views.Task({ model: task });
            this.$el.append(taskView.render().el);
        }
    });

    var tasks = new App.Collections.Tasks([
        {
            title: 'Go to store',
            priority: 4
        },
        {
            title: 'Go to mall',
            priority: 3
        },
        {
            title: 'Get to work',
            priority: 5
        }
    ]);
    var addTaskView = new App.Views.AddTask({ collection: tasks });
    var tasksView = new App.Views.Tasks({ collection: tasks });
    $('div.tasks').append(tasksView.render().el);
})();

所以模型验证工作正常......唯一的pb是collection.add不验证新添加的模型....是强制验证的一种方法吗?

谢谢, 拉雷什

2 个答案:

答案 0 :(得分:2)

来自fine manual

  

验证 model.validate(attributes, options)

     

[...]默认情况下,验证save之前调用,但也可以   如果set通过,则在{validate:true}之前调用。

Collection#add不会致电save,也不会使用set选项致电validate: true。如果您想在add期间进行验证,请说明:

collection.add(models, { validate: true });

这将validate:true一直到Model#set

快速浏览一个简化示例可能会有所帮助:

var M = Backbone.Model.extend({
    set: function() {
        console.log('setting...');
        Backbone.Model.prototype.set.apply(this, arguments);
    },
    validate: function() {
        console.log('validating...');
        return 'Never!';
    }
});
var C = Backbone.Collection.extend({
    model: M
});
var c = new C;
c.on('add', function() {
    console.log('Added: ', arguments);
});
c.on('invalid', function() {
    console.log('Error: ', arguments);
});

现在,如果我们这样做(http://jsfiddle.net/ambiguous/7NqPg/):

c.add(
    { where: 'is', pancakes: 'house?' },
    { validate: true }
);

您会看到使用set调用validate: true,将调用validate,您将收到错误消息。但如果你这样说(http://jsfiddle.net/ambiguous/7b2mn/):

c.add(
    { where: 'is', pancakes: 'house?' },
    {add: true, merge: false, remove: false} // Your options
);

您会看到set在没有validate: true的情况下被调用,validate被调用,模型将被添加到集合中。< / p>


上述行为非常强烈暗示但未明确指定,因此您可能不想信任它。 Model#initialize确实说:

  

您可以传递属性的初始值,该值在模型上为set

set明确提到了validate选项。但是,无法保证Collection#add会向模型构造函数或set发送选项,或者模型的构造函数会将选项发送到set。因此,如果你想要真正的偏执和未来证明,你可以快速检查这个“选项一直到set”行为到您的测试套件;然后,如果它改变了你就会知道它并且你可以解决它。

答案 1 :(得分:1)

如果将选项传递给集合添加方法,则不会调用验证方法,并且由于此情况下的参数都设置为默认值,因此无需传递它们

 this.collection.add(task); 

你可能想看看这个问题。 Prevent Backbone.js model from validating when first added to collection