Reputation: 5096
If I am using Backbone, which (or both) of these is the "correct" way to set data?
// Logic in the Model
// Can call from anywhere that has access
SomeModel = Backbone.Model.extend({
defaults: {
visible: false
},
toggle: function(visible){
visible = typeof visible !== "undefined" ? visible : !this.get("visible");
this.set({visible: visible});
}
});
OR
// Logic in the View
SomeView = Backbone.View.extend({
events: {
"click .toggle" : "toggleVisibility"
},
toggleVisibility: function(){
this.model.set({visible: !this.model.get("visible")});
}
});
Obviously either one of these work, but my question is how much of that logic should be pushed off to the model? If, for instance, I have a situation that updates two variables:
this.model.set({visible: false, foo: bar, something: else});
Would it make sense to create a function on the model like this:
someFunction: function(visible, foo, something){
this.set({visible: visible, foo: foo, something: something});
}
That just seems like overkill to me, but the set({}) logic in the view feels dirty.
Thoughts?
Upvotes: 2
Views: 2727
Reputation: 2639
Similar question, with a great answer, here: Should views set model data?
As with most previous commenters, the general answer seems to be: if you're changing display elements, set data in the View. If you're setting business logic, set data in the Model.
Upvotes: 0
Reputation: 1549
It seems that you're mixing view logic into your models which isn't really a great idea. I would imagine there is some data in your model that is relevant to whether the view that has it bound should be visible (something like deleted: true, etc.) but you should toggle visibility based on that attribute changing. I would envision something like:
SomeModel = Backbone.Model.extend();
SomeView = Backbone.View.extend({
events: {
"click .toggle" : "toggleDeleted"
},
initialize: function() {
this.model.on('change:deleted', this.toggleVisibility);
},
toggleDeleted: function() {
var deleted = this.model.get('deleted');
this.model.set({deleted: !deleted});
},
toggleVisibility: function(){
this.$el.toggle(); // jQuery function toggling visibility
}
});
// Somewhere in your "controller" logic
var someModel = new SomeModel({deleted: false});
var someView = new SomeView({model: someModel, el: DOMelement});
That way all your view logic is in your view and not your model. The model is empty since backbone has no need to define a schema, but generally you'll add functionality there at some point.
Upvotes: 0
Reputation: 902
It might feel dirty because you're used to the differentiation between views and controllers. In Backbone.js, however, it does not exist - views are also controllers. When you understand that, the interactions with the models become a whole lot easier on the eyes...
In my opinion, the correct way to solve your problem is a combination of the methods you introduced. Leave SomeModel.toggle
in place, and in your view do:
toggleVisibility: function() { this.model.toggle(); }
Upvotes: 1
Reputation: 17808
I would have the toggle function a member of the model, and call it from your view(s), hiding the implementation details. Remember a model can be represented by more then one view at a time, so any common model logic should be centralized there.
Maybe something like:
// Logic in the Model
// Can call from anywhere that has access
SomeModel = Backbone.Model.extend({
defaults: {
visible: false
},
toggle: function(visible){
visible = typeof visible !== "undefined" ? visible : !this.get("visible");
this.set({visible: visible});
}
});
OR
// Logic in the View
SomeView = Backbone.View.extend({
initialize: function() {
this.model.bind('change:visibility',this.changeVisibility);
}
events: {
"click .toggle" : "toggleVisibility"
},
toggleVisibility: function(){
this.model.toggle();
}
changeVisibility: function() {
........
/// seems like alot of extra work to get to this point
/// but remember, all views for the model are will receive this
/// event now, not just the one that received the UI click
/// whether or not that's the behavior you want is up to you.
........
}
});
Upvotes: 1