Skip to content

Commit

Permalink
allow modelEvents and collectionEvents to be functions directly, that…
Browse files Browse the repository at this point in the history
… return a hash
  • Loading branch information
Derick Bailey committed Dec 24, 2012
1 parent 2eb7d28 commit ab3c737
Show file tree
Hide file tree
Showing 11 changed files with 171 additions and 86 deletions.
3 changes: 3 additions & 0 deletions changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@
* Modules
* Fixed a bug where a module would not be started without an explicit definition for that module (#388 & #400)

* All Views
* Allow `modelEvents` and `collectionEvents` to be a function that returns a hash

### v1.0.0-rc2 [view commit logs](https://github.com/marionettejs/backbone.marionette/compare/v1.0.0-rc1...v1.0.0-rc2)

* CollectionView / CompositeView
Expand Down
17 changes: 17 additions & 0 deletions docs/marionette.view.md
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,23 @@ Backbone.Marionette.CompositeView.extend({

This works for both `modelEvents` and `collectionEvents`.

### Event Configuration As Function

A function can be used to declare the event configuration, as long as
that function returns a hash that fits the above configuration options.

```js
Backbone.Marionette.CompositeView.extend({

modelEvents: function(){
return { "change:name": "someFunc" };
}

});
```

This works for both `modelEvents` and `collectionEvents`.

## View.serializeData

The `serializeData` method will serialize a view's model or
Expand Down
7 changes: 7 additions & 0 deletions lib/backbone.marionette.js
Original file line number Diff line number Diff line change
Expand Up @@ -575,6 +575,7 @@ Marionette.EventAggregator = Backbone.Wreqr.EventAggregator.extend({
// configuration. Multiple handlers can be separated by a space. A
// function can be supplied instead of a string handler name.
Marionette.bindEntityEvents = (function(){
"use strict";

// Bind the event to handlers specified as a string of
// handler names on the target object
Expand All @@ -601,6 +602,12 @@ Marionette.bindEntityEvents = (function(){
return function(target, entity, bindings){
if (!entity || !bindings) { return; }

// allow the bindings to be a function
if (_.isFunction(bindings)){
bindings = bindings.call(target);
}

// iterate the bindings and bind them
_.each(bindings, function(methods, evt){

// allow for a function as the handler,
Expand Down
2 changes: 1 addition & 1 deletion lib/backbone.marionette.min.js

Large diffs are not rendered by default.

7 changes: 7 additions & 0 deletions lib/core/amd/backbone.marionette.js
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,7 @@
// configuration. Multiple handlers can be separated by a space. A
// function can be supplied instead of a string handler name.
Marionette.bindEntityEvents = (function(){
"use strict";

// Bind the event to handlers specified as a string of
// handler names on the target object
Expand All @@ -268,6 +269,12 @@
return function(target, entity, bindings){
if (!entity || !bindings) { return; }

// allow the bindings to be a function
if (_.isFunction(bindings)){
bindings = bindings.call(target);
}

// iterate the bindings and bind them
_.each(bindings, function(methods, evt){

// allow for a function as the handler,
Expand Down
2 changes: 1 addition & 1 deletion lib/core/amd/backbone.marionette.min.js

Large diffs are not rendered by default.

7 changes: 7 additions & 0 deletions lib/core/backbone.marionette.js
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,7 @@ Marionette.EventAggregator = Backbone.Wreqr.EventAggregator.extend({
// configuration. Multiple handlers can be separated by a space. A
// function can be supplied instead of a string handler name.
Marionette.bindEntityEvents = (function(){
"use strict";

// Bind the event to handlers specified as a string of
// handler names on the target object
Expand All @@ -250,6 +251,12 @@ Marionette.bindEntityEvents = (function(){
return function(target, entity, bindings){
if (!entity || !bindings) { return; }

// allow the bindings to be a function
if (_.isFunction(bindings)){
bindings = bindings.call(target);
}

// iterate the bindings and bind them
_.each(bindings, function(methods, evt){

// allow for a function as the handler,
Expand Down
2 changes: 1 addition & 1 deletion lib/core/backbone.marionette.min.js

Large diffs are not rendered by default.

120 changes: 120 additions & 0 deletions spec/javascripts/view.entityEvents.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
describe("view entity events", function(){

describe("when a view has string-based model and collection event configuration", function(){
var view;

var View = Backbone.Marionette.View.extend({
modelEvents: { 'model-event': 'modelEventHandler modelEventHandler2' },
collectionEvents: { 'collection-event': 'collectionEventHandler collectionEventHandler2' },

modelEventHandler: jasmine.createSpy("model event handler"),
collectionEventHandler: jasmine.createSpy("collection event handler"),
modelEventHandler2: jasmine.createSpy("model event handler2"),
collectionEventHandler2: jasmine.createSpy("collection event handler2")
});

beforeEach(function(){
view = new View({
model: new Backbone.Model(),
collection: new Backbone.Collection()
});
});

it("should wire up model events", function(){
view.model.trigger("model-event");
expect(view.modelEventHandler).toHaveBeenCalled();
expect(view.modelEventHandler2).toHaveBeenCalled();
});

it("should wire up collection events", function(){
view.collection.trigger("collection-event");
expect(view.collectionEventHandler).toHaveBeenCalled();
expect(view.collectionEventHandler2).toHaveBeenCalled();
});

});

describe("when a view has function-based model and collection event configuration", function(){
var view;

var View = Backbone.Marionette.View.extend({
modelEvents: {
'model-event': jasmine.createSpy("model event handler")
},
collectionEvents: {
'collection-event': jasmine.createSpy("collection event handler")
}
});

beforeEach(function(){
view = new View({
model: new Backbone.Model(),
collection: new Backbone.Collection()
});
});

it("should wire up model events", function(){
view.model.trigger("model-event");
expect(view.modelEvents['model-event']).toHaveBeenCalled();
});

it("should wire up collection events", function(){
view.collection.trigger("collection-event");
expect(view.collectionEvents['collection-event']).toHaveBeenCalled();
});

});

describe("when a view has model event config with a specified handler method that doesn't exist", function(){
var getBadViewInstance;

var View = Backbone.Marionette.View.extend({
modelEvents: { "foo": "does_not_exist" }
});

beforeEach(function(){
getBadViewInstance = function(){
new View({ model: {} })
}
});

it("should error when method doesn't exist", function(){
expect(getBadViewInstance).toThrow("Method 'does_not_exist' was configured as an event handler, but does not exist.");
});
});

describe("when configuring entity events with a function", function(){
var view, modelHandler, collectionHandler;

beforeEach(function(){
modelHandler = jasmine.createSpy("model handler");
collectionHandler = jasmine.createSpy("collection handler");

var View = Backbone.Marionette.View.extend({
modelEvents: function(){
return {'model-event': modelHandler};
},
collectionEvents: function(){
return {'collection-event': collectionHandler};
}
});

view = new View({
model: new Backbone.Model(),
collection: new Backbone.Collection()
});

view.model.trigger('model-event');
view.collection.trigger('collection-event');
});

it("should trigger the model event", function(){
expect(modelHandler).toHaveBeenCalled();
});

it("should trigger the collection event", function(){
expect(collectionHandler).toHaveBeenCalled();
});
});

});
83 changes: 0 additions & 83 deletions spec/javascripts/view.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,89 +27,6 @@ describe("base view", function(){
});
});

describe("when a view has string-based model and collection event configuration", function(){
var view;

var View = Backbone.Marionette.View.extend({
modelEvents: { 'model-event': 'modelEventHandler modelEventHandler2' },
collectionEvents: { 'collection-event': 'collectionEventHandler collectionEventHandler2' },

modelEventHandler: jasmine.createSpy("model event handler"),
collectionEventHandler: jasmine.createSpy("collection event handler"),
modelEventHandler2: jasmine.createSpy("model event handler2"),
collectionEventHandler2: jasmine.createSpy("collection event handler2")
});

beforeEach(function(){
view = new View({
model: new Backbone.Model(),
collection: new Backbone.Collection()
});
});

it("should wire up model events", function(){
view.model.trigger("model-event");
expect(view.modelEventHandler).toHaveBeenCalled();
expect(view.modelEventHandler2).toHaveBeenCalled();
});

it("should wire up collection events", function(){
view.collection.trigger("collection-event");
expect(view.collectionEventHandler).toHaveBeenCalled();
expect(view.collectionEventHandler2).toHaveBeenCalled();
});

});

describe("when a view has function-based model and collection event configuration", function(){
var view;

var View = Backbone.Marionette.View.extend({
modelEvents: {
'model-event': jasmine.createSpy("model event handler")
},
collectionEvents: {
'collection-event': jasmine.createSpy("collection event handler")
}
});

beforeEach(function(){
view = new View({
model: new Backbone.Model(),
collection: new Backbone.Collection()
});
});

it("should wire up model events", function(){
view.model.trigger("model-event");
expect(view.modelEvents['model-event']).toHaveBeenCalled();
});

it("should wire up collection events", function(){
view.collection.trigger("collection-event");
expect(view.collectionEvents['collection-event']).toHaveBeenCalled();
});

});

describe("when a view has model event config with a specified handler method that doesn't exist", function(){
var getBadViewInstance;

var View = Backbone.Marionette.View.extend({
modelEvents: { "foo": "does_not_exist" }
});

beforeEach(function(){
getBadViewInstance = function(){
new View({ model: {} })
}
});

it("should error when method doesn't exist", function(){
expect(getBadViewInstance).toThrow("Method 'does_not_exist' was configured as an event handler, but does not exist.");
});
});

describe("when using listenTo for the 'close' event on itself, and closing the view", function(){
var close;

Expand Down
7 changes: 7 additions & 0 deletions src/marionette.bindEntityEvents.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
// configuration. Multiple handlers can be separated by a space. A
// function can be supplied instead of a string handler name.
Marionette.bindEntityEvents = (function(){
"use strict";

// Bind the event to handlers specified as a string of
// handler names on the target object
Expand All @@ -40,6 +41,12 @@ Marionette.bindEntityEvents = (function(){
return function(target, entity, bindings){
if (!entity || !bindings) { return; }

// allow the bindings to be a function
if (_.isFunction(bindings)){
bindings = bindings.call(target);
}

// iterate the bindings and bind them
_.each(bindings, function(methods, evt){

// allow for a function as the handler,
Expand Down

0 comments on commit ab3c737

Please sign in to comment.