2013-06-23 71 views
2

我对骨干很陌生,想测试一个处理待办事项列表的简单脚本。这里是我迄今为止所使用的代码:骨干集合添加不会触发模型验证

(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

fine manual

验证model.validate(attributes, options)

[...]默认情况下验证save之前调用,但也set之前如果{validate:true}是被称为 通过。

Collection#add不叫save也不叫setvalidate: 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: truevalidate将被调用,并且你会得到一个错误。但是,如果你说这(http://jsfiddle.net/ambiguous/7b2mn/):

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

你会看到,set被称为无validate: truevalidate被调用,该模型将添加到集合。


上述行为是相当强烈的暗示,但没有明确指定,所以你可能不想相信它。Model#initialize并说:

你可以在的初始值将属性,这将是set型号。

set明确提到了validate选项。但是,不能保证Collection#add将选项发送给模型构造函数或set,或者模型的构造函数将发送选项给set。所以,如果你想成为真正的偏执狂和未来的证明,你可以添加一个快速检查这个“选项一直到set”行为到你的测试套件;那么,如果它发生变化,你会知道它,你可以修复它。

+0

谢谢...给我这样的新手一个简短的提示...如果你发送到add方法,模型“{validate:true}”的一个实例将不起作用......但是如果你发送一个包含模型属性和'{validate:true}'将工作(将调用验证函数)....所以再次... **这不起作用=>'var task = new App.Models.Task({title: newTaskTitle});这个工程=>'collection.add({title:newTaskTitle},{validate:true});'* * – user2030809

1

如果你通过选项到您的收藏添加方法,验证方法不会被调用,为你在这种情况下,参数都设置为默认值,所以不需要通过他们

this.collection.add(task); 

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

+0

你会注意到nikoshr的回答包括一个重要的警告:“它可能会把事情弄垮”。选项欺骗不再适用于收藏工作方式的变化。 –