Comments (12)
If you want to handle events for a nested collection, you can bind to that collection, just like in plain Backbone. This should work (does work as far as I can tell) for change
, add
and remove
.
As per your example:
e.get( 'rsvps' ).bind( 'all', function() {
console.log( 'event fired on Event.rsvps; arguments=%o', arguments );
});
from backbone-relational.
Hmm, sorry, this is something that should be working I guess (binding on rsvps:add
and rsvps:remove
from event).
from backbone-relational.
Checked again, this seems fine for me? Action sequence:
console.log( 'set {response:yes} on r' );
r.set( { 'response': 'yes' } );
console.log( 'remove r from e' );
e.get( 'rsvps' ).remove( r );
console.log( 'adding another rsvp' );
e.get( 'rsvps').add( { name: "Jacob" } );
Events logged:
set {response:yes} on r
event fired on Event.rsvps; arguments=["change:response", ...
event fired on Rsvp; arguments=["change:response", ...
event fired on Event.rsvps; arguments=["change", ...
event fired on Rsvp; arguments=["change", ...
remove r from e
event fired on Event.rsvps; arguments=["remove", ...
event fired on Rsvp; arguments=["remove", ...
event fired on Rsvp; arguments=["update:event", ...
event fired on Event; arguments=["remove:rsvps", ...
event fired on Event.rsvps; arguments=["relational:remove", ...
adding another rsvp
event fired on Event.rsvps; arguments=["add", ...
event fired on Event.rsvps; arguments=["update:event", ...
event fired on Event; arguments=["add:rsvps", ...
event fired on Event.rsvps; arguments=["relational:add", ...
from backbone-relational.
@rjharmon: ahh, okay. The idea I got from your post was just that you had issues with remove
events not getting fired.
I don't think firing a change
event for every modification on any relation by defaults would be a good idea, but something like that is pretty easy to do by adding a helper method to Backbone.RelationalModel
, since this._relations
actually does give you the related model or collection. Quick first attempt that you could build from:
Backbone.RelationalModel.prototype.bindRelationEvents = function() {
var dit = this;
_.each( this.getRelations(), function( relation ) {
relation.related && relation.related.bind( 'all', function() {
dit.trigger.apply( dit, arguments );
// Or even simply `dit.render()`, if the number of events is reasonable...
} );
});
};
then call this.bindRelationEvents
for objects you'd like to receive all events from their relations as well.
from backbone-relational.
I made this work for item adds/removes on a related collection using this.get('features-has-many-collection').bind("all", function() { this.change() }, but I'm not seeing how to iterate the collections on a model, as this._relations doesn't have meta-data for actually getting to the associated collections.
Recommendations?
from backbone-relational.
I'm getting the same behavior on Backbone 0.5.3 and Backbone-Relational 0.4.0. Changes to models in nested collections fire events on the nested collection, but do not fire on the parent-relation model.
E.g. (in Coffeescript)
class Event extends Backbone.RelationalModel
relations: [{
type: Backbone.HasMany,
key: 'rsvps'
relatedModel: 'Rsvp'
collectionType: 'RsvpsCollection'
createModels: true
reverseRelation:
key: 'event'
includeInJSON: 'id'
}]
...
At run time (in Firebug/Acebug)
e.bind 'all', () ->
console.log 'event fired on Event object with arguments: ', arguments
r = e.get('rsvps').first()
r.bind 'all', () ->
console.log 'event fired on Rsvp object with arguments: ', arguments
r.set {response: 'yes'}
# => event fired on Rsvp object with arguments: ["change", Rsvp ... ]
r.destroy()
# => event fired on Rsvp object with arguments: ["remove", Rsvp ... ]
# => event fired on Rsvp object with arguments: ["update:event", Rsvp ... ]
# => event fired on Event object with arguments: ["remove:rsvps", Rsvp ... ]
# => event fired on Rsvp object with arguments: ["destroy", Rsvp ... ]
from backbone-relational.
I opened this ticket because I was dissatisfied with the need to call bind('all') on all of my nested collections, in order to get notified of their changes. Calling those bind()'s myself works fine, but I wished for a single convenience method so that I'd receive a change() notification on my model when any of its nested collections change. It's pretty specific to some pretty common cases.
this.notifyOnRelationsChanged();
this.notifyOnRelationsChanged(function() { this.change() });
this.notifyOnRelationsChanged({only:['items', 'books']})
this.notifyOnRelationsChanged({except: ['interestedUsers']});
from backbone-relational.
@PaulUithol Strange, I just double checked this again in Firebug/Acebug and I'm still not seeing change events:
#>> lang=cf
e = router.events.first()
rsvps = e.get 'rsvps'
r = rsvps.first()
e.bind 'all', () ->
log 'Event event fired. Args: ', arguments
r.bind 'all', () ->
log 'RSVP event fired. Args: ', arguments
log 'changing rsvp'
r.set response: 'no'
log 'deleting rsvp'
r.destroy()
Output:
changing rsvp
deleting rsvp
DELETE http://localhost:3000/rsvps/29
200 OK
2.63s
RSVP event fired. Args: ["remove", Rsvp ...
RSVP event fired. Args: ["remove", Rsvp ...
RSVP event fired. Args: ["update:event", Rsvp ...
Event event fired. Args: ["remove:rsvps", Rsvp ...
RSVP event fired. Args: ["destroy", Rsvp ...
I defined the relations
array only in Backbone.Models.Events, but it has the reverseRelation
attribute defined. Could this be causing the issue?
(Btw, if this is too tangential to the original post I can create a new issue)
from backbone-relational.
Are there any news on this? We have a Backgrid table in our application that renders related models in a special cell and also offers an editor for that cell to change the related models. Changing the related models is no problem, but the application has to perform further actions when that relation changes. At the moment our custom cell editor just handles this too, but that is not a satisfying solution because it does not follow the principal of separation of concerns.
The problem is that, as mentioned above, the change event is not triggered for the relation's attribute.
I. e., we have a parent model ParentModel
that has a HasMany
relationship called 'related_items'.
var ParentModel = Backbone.RelationalModel.extend({
defaults: function() {
return {
related_items: new ItemCollection();
};
},
relations: [
{
key: 'related_items',
type: Backbone.HasMany,
relatedModel: ItemCollection.prototype.model
// ...
}
]
});
Listening to the 'change:related_items' on the ParentModel
or a ParentModelCollection
is pretty useless because that event is never triggered. Not even if you switch out the 'related_items' collection entirely: my_parent_model.set('related_items', new_collection);
does not trigger the event.
Following code would seem totally natural to me
// this refers to some view which handles displaying a ParentModelCollection
this.listenTo(this.collection, 'change:related_items', this.changeCallback);
but as I understand this conversation, that is deliberately not supported. Instead I would have to iterate over each item in the collection and add a listener directly on each related collection, something like this
this.collection.each(function(model) {
this.listenTo(model.get('related_items'), 'change', this.changeCallback);
}, this);
But that is totally impractical, because whenever new models are added or removed from my ParentModelCollection
or whenever the referenced 'related_items' collection changes, I have to remove and re-bind my changeCallback
for that particular model.
This is not the only time that we stumble on this problem. Our application needs to react to changed HasMany
relations quite often. So I don't understand your statement:
I don't think firing a change event for every modification on any relation by defaults would be a good idea,
Why don't you think 'bubbling up' the change event to the parent model was a good idea? Can't be that much of an impact on performance I think and it would definitely make reacting to changed HasMany
relations a lot more concise and straight forward.
from backbone-relational.
That would cause a lot of events being fired when updating large collections.
@floriandammeyer Can you check out this jsfiddle and fork it to show a failing test for your use case?
from backbone-relational.
I will take a look at it on the weekend
from backbone-relational.
Finally got the time now, I forked your fiddle here: http://jsfiddle.net/ee19fo4r/1/
In the first test case, I changed the expected behavior so that changing a model inside the child collection would also trigger a change event on the parent model. That behavior however does not make sense at all, because it would conflict with the expected behavior of the following test. You would not be able to determine what actually changed: a model inside the collection or the collection itself.
The following test expects a change event to be fired on the parent model if the related collection has been substituted entirely. I think this test case should be implemented, because it is the behavior that I expected from Backbone.Relational. If you switch out the collection entirely by calling parent.set('children', new Backbone.Collection());
, it should trigger a change event for the children
attribute just like chaning a normal attribute (like name
) would do. However, at this moment that does not happen. Switching out the related collection happens silently, and this is problematic for my initial use case. Example:
// ...
Backbone.View.extend({
initialize: function()
{
// This view should react to changes that happen to child models
// of the given parent models, so we iterate over all models in the
// given collection to add an event handler
this.collection.each(function(model) {
this.listenTo(model.get('children'), 'change', this.handleChangedChild);
}, this);
// Obviously, if the related 'children' collection changes on any of the
// parent models, we have to re-bind our listener to the new collection!
this.listenTo(this.collection, 'change:children', function(model) {
this.listenTo(model.get('children'), 'change', this.handleChangedChild);
// Note: I did not implement any garbage-collection here
// that removes the old listeners for brevity
});
}
// ...
});
// ...
In our application a related collection is being substituted quite frequently. Unfortunately, because no change event is triggered in that case, above code does not work as expected.
from backbone-relational.
Related Issues (20)
- Backbone send null for unset relations HOT 1
- Backbone Relational dealing with model instances with the same ID HOT 2
- Retain model in collection when unsetting on another relationship HOT 1
- Models without id (only cid) are not registered in Backbone.Relational.Store HOT 1
- Doesn't work with lodash 4.1.0 HOT 1
- Is this project abandoned? HOT 6
- Backbone 1.3.2 support HOT 2
- using toJSON to serialize data HOT 3
- Update documentation for ES2015/CommonJS importing
- JSBin example HOT 1
- Rename Backbone-relational to backbone.relational HOT 4
- Double imports for using with webpack HOT 5
- ES2015 Refactor (Release Checklist) HOT 1
- Store causing huge memory retention and cleanup takes forever HOT 2
- How do I get Backbone-relational working with ES6? HOT 6
- Problem defining relations: "model does not inherit from Backbone.RelationalModel" HOT 6
- getAsync() fails when retrieving to many models using set URL HOT 4
- don't initialize related Model/Collection in defaults HOT 2
- Collection instances share `options` object by reference which is unexpected
- Backbone-relational compactibility with typescript
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from backbone-relational.