Permalink
Browse files

Added support for binding to a view with a collection. Closes #18

  • Loading branch information...
1 parent 1be7a69 commit 60cf05b3d2df9d1face7ccd2028134190f11b554 @thedersen committed Feb 19, 2012
Showing with 117 additions and 3 deletions.
  1. +2 −1 README.md
  2. +32 −2 backbone.validation.js
  3. +83 −0 tests/collections.js
View
@@ -545,9 +545,10 @@ The message can contain placeholders for arguments that will be replaced:
#### v0.5.0
* Support for Backbone v0.9.1
+* Support for object/nested validation (Fixed #20, thanks to [AndyUK](https://github.com/andyuk))
+* Support for binding to a view with a collection of models
* Context (this) in custom validators is the `Backbone.Validation.validators` object
* Calling `unbind` on a view without model no longer throws (Fixes #17)
-* Support for object/nested validation (Fixed #20, thanks to [AndyUK](https://github.com/andyuk))
* Method validators get a computed model state (i.e. the state of the model if the current set operation succeeds) as the third argument (Fixes #22)
#### v0.4.0
@@ -166,6 +166,14 @@ Backbone.Validation = (function(Backbone, _, undefined) {
}
};
+ var collectonAdd = function(model) {
+ bindModel(this.view, model, this.options);
+ };
+
+ var collectionRemove = function(model) {
+ unbindModel(model);
+ };
+
return {
version: '0.5.0',
@@ -175,12 +183,34 @@ Backbone.Validation = (function(Backbone, _, undefined) {
bind: function(view, options) {
var model = view.model,
+ collection = view.collection,
opt = _.extend({}, defaultOptions, Backbone.Validation.callbacks, options);
- bindModel(view, model, opt);
+
+ if(model) {
+ bindModel(view, model, opt);
+ }
+ if(collection) {
+ collection.each(function(model){
+ bindModel(view, model, opt);
+ });
+ collection.bind('add', collectonAdd, {view: view, options: opt});
+ collection.bind('remove', collectionRemove);
+ }
},
unbind: function(view) {
- unbindModel(view.model);
+ var model = view.model,
+ collection = view.collection;
+ if(model) {
+ unbindModel(view.model);
+ }
+ if(collection) {
+ collection.each(function(model){
+ unbindModel(model);
+ });
+ collection.unbind('add', collectonAdd);
+ collection.unbind('remove', collectionRemove);
+ }
}
};
} (Backbone, _));
View
@@ -0,0 +1,83 @@
+buster.testCase('Binding to view with collection', {
+ setUp: function() {
+ var View = Backbone.View.extend({
+ render: function() {
+ Backbone.Validation.bind(this);
+ }
+ });
+ this.Model = Backbone.Model.extend({
+ validation: {
+ name: function(val) {
+ if (!val) {
+ return 'Name is invalid';
+ }
+ }
+ }
+ });
+ var Collection = Backbone.Collection.extend({
+ model: this.Model
+ });
+ this.collection = new Collection([{name: 'Tom'}, {name: 'Thea'}]);
+ this.view = new View({
+ collection: this.collection
+ });
+
+ this.view.render();
+ },
+
+ tearDown: function() {
+ this.view.remove();
+ },
+
+ "binds existing models in collection when binding": function() {
+ assert.defined(this.collection.at(0).validate);
+ assert.defined(this.collection.at(1).validate);
+ },
+
+ "binds model that is added to the collection": function() {
+ var model = new this.Model({name: 'Thomas'});
+ this.collection.add(model);
+
+ assert.defined(model.validate);
+ },
+
+ "binds models that are batch added to the collection": function() {
+ var model1 = new this.Model({name: 'Thomas'});
+ var model2 = new this.Model({name: 'Hans'});
+ this.collection.add([model1, model2]);
+
+ assert.defined(model1.validate);
+ assert.defined(model2.validate);
+ },
+
+ "unbinds model that is removed from collection": function() {
+ var model = this.collection.at(0);
+ this.collection.remove(model);
+
+ refute.defined(model.validate);
+ },
+
+ "unbinds models that are batch removed from collection": function() {
+ var model1 = this.collection.at(0);
+ var model2 = this.collection.at(1);
+ this.collection.remove([model1, model2]);
+
+ refute.defined(model1.validate);
+ refute.defined(model2.validate);
+ },
+
+ "unbinds all models in collection when unbinding view": function() {
+ Backbone.Validation.unbind(this.view);
+
+ refute.defined(this.collection.at(0).validate);
+ refute.defined(this.collection.at(1).validate);
+ },
+
+ "unbinds all collection events when unbinding view": function() {
+ var that = this;
+ Backbone.Validation.unbind(this.view);
+
+ refute.exception(function() { that.collection.trigger('add'); });
+ refute.exception(function() { that.collection.trigger('remove'); });
+ }
+});

0 comments on commit 60cf05b

Please sign in to comment.