What is the difference between properties and attributes of a Backbone model.
I believe one would use attributes to trigger model changes when the model gets modified.
In the below example.
var Vehicle = Backbone.Model.extend({prop1:'1'});
var v1 = new Vehicle({prop1 : '1111'});
console.log(v1.prop1); // accessing the property
console.log(v1.get('prop1')); // accessing the attribute
The object v1 has both a property called prop1 and also an attribute called prop1. There is no relation between them.
The difference is really that a property is a language feature (Javascript), whereas an attribute is a feature of the Backbone framework. To put it another way, a property exists independently of Backbone, whereas an attribute relies on the Backbone framework and its infrastructure.
Specifically, attributes participate in all the model-related things:
sync (when you call save or fetch)
validation on save
view rendering (via toJSON)
events and notification
Related
I am developing a rich client application using Backbone.js and have encountered a situation where I need to fetch 3 values from three database tables and display them.
The rub, however, is that they are not part of my models and I have no need to synchronize them. They are for display purposes only. Should I created a child view which adds them to the DOM as part of the render() method? I'd prefer not to just hack some jQuery code together -but- it doesn't seem to fit nicely into my mental picture of Backbone models and views either.
The rule of thumb in MVCs like Backbone is that the data structure should always be stored in the model layer imo. In your case this could either mean extending your current models with those ui state related attributes (recommended) or create a new model and pass it to the views as an option:
var myModel = new MyModel();
var newModel = new NewModel();
var myView = new View({
model: myModel,
newModel: newModel
});
later in the view you can access to the newModel as this.options.newModel
I'm trying to retrieve the model, because I need to access certain attributes, but I cannot. I'm inside a view, which extends another one. This is how the view looks like:
var ImageGridControlView = GridControlView.extend({
//.... stuff ....
alert(this.model.get('property')) //This gives me an error in console and nothing is alerted.
});
In the class that the above code extends, the model can be retrieved, like this:
var GridControlView = ControlView.extend({
//.... stuff ....
alert(this.model.get('property')) //This shows the property value correctly
});
Why can't the model be retrieved from ImageGridControlView? What is the persistence of models across different classes, children, etc? I'm new to Backbone, and the official documentation only covers models superficially.
Your snippets are too small to actually find the problem, so we have to just guess. Most likely candidates are:
you are accessing this.model inside a function triggered by an event binding that is not properly bound, so this isn't actually your view instance. It could be a the source DOM element of the window object instead.
You aren't passing a model property in the options object provided to the view's constructor
I have 2 post collections and a model as follows.
# router file
#posts = new MyApp.Collections.PostsCollection()
#posts.reset options.posts
#followed_posts = new MyApp.Collections.PostsCollection()
#followed_posts.reset options.followed_posts
# Post model file
class MyApp.Models.Post extends Backbone.Model
paramRoot: 'post'
follow_post: ->
# ajax call
console.log "_________Index:#{this.collection.indexOf(this);}"
console.log this.collection
console.log "_________Followed:"
console.log #followed_posts
class MyApp.Collections.PostsCollection extends Backbone.Collection
model: MyApp.Models.Post
url: '/posts_all'
What I am trying to do is when one of the model changed in one collection, I want to update the other model in other collection too.
These collections may or may not hold same models.
So let's say if a model in #posts changed in my Post model, I want to update that model in #followed_posts too. If #followed_posts doesn't have that model, I need to add a duplicate of the model to #followed_posts collection.
I can access the collection that model belongs, but I cannot access the other collection.
Any ideas appreciated, thanks.
If the two collections are antisocial and can't talk directly to each other, which is usually good design, then you'll need an intermediary -- a global event dispatcher. When a model changes, propagate that event to the dispatcher along with a reference to the model. Listen for the event in the other collection and use the model passed to check for existence and respond as needed.
EDIT:
Backbone's documentation mentions this pattern:
For example, to make a handy event dispatcher that can coordinate
events among different areas of your application: var dispatcher =
_.clone(Backbone.Events)
But in fact, this is such a common pattern that the Backbone object itself is extended with Events. So you can just do:
// In your Post model
#on "change", -> Backbone.trigger "post:change", this, #collection
// And then something like this in the collection class definition:
#listenTo Backbone, "post:change", (model, collection) =>
if post = #get model.cid
post.set model.toJSON()
else
#add model
Also, is followed posts a subset of posts? If so, why not put an attribute on the model designating it as followed? Then you could find all followed posts with a simple filter function.
I would strongly suggest that you should consider having a single collection and add some kind of attribute in the model to differentiate between what kind of posts they are.
I took a small code from backbone home site, and consoled the function, in this example, sidebar.on('change:color'), takes the function. but it requires two parameter, one is abiously we need that is 'color', and we defining the element inside the function, still why we giving another parameter as 'model' here, what that parameter does?
if i remove that parameter send only the color, the function doesn't work at all... any one help me to understand this?
sample function here:
var Sidebar = Backbone.Model.extend({
promptColor : function(){
var cssColor = prompt('Please enter a css color');
this.set({color:cssColor});
}
});
window.sidebar = new Sidebar;
sidebar.on('change:color',function(model,color){ // what model parameter do here?
console.log(model);
$('#sidebar').css({
background:color
})
})
sidebar.set({color:'green'});
sidebar.promptColor();
when i console the model i got this:
d
_callbacks: Object
_changing: false
_escapedAttributes: Object
_pending: Object
_previousAttributes: Object
_silent: Object
attributes: Object
changed: Object
cid: "c1"
__proto__: x
It is possible that you want to know which model was affected.
Consider a case where you are listening to an event on a collection instead. Which model's color value was modified? The model parameter tells you this.
Also, consider a case where the same handler is listening to "change:color" on multiple models. Again, you might want to know which model sent the event.
Just like in other event-driven environments, the "sender" is always passed along with the event data. model, in this case, is the sender.
Backbone is a Javascript MVC framework. (Unlike standard MVC, Backbone doesn't have controllers, instead it has collections).
The model you are receiving is a standard model from the MVC paradigm. Model's are the underlying data structures that hold the data that the user is working with.
When you do
sidebar.on('change:color', function(model, color) {
// some code here
});
you are attaching an event handler to the sidebar model. Specifically, you are saying that when the color attribute on this model changes, call the function. Since this event can and will trigger at a later point in time, Backbone passes the event handler function two arguments: the first is the model on which the event fired, and the second is the attribute that changed.
The arguments are passed in a specific order, that is model is the first argument, and the changed attribute is the second. Thus if you omit the model argument from your event handler function, the passed in model gets assigned to color, and color doesn't get assigned to any argument.
Recommended reading:
More about MVC and models
More about backbone models
A Backbone.Model object maintains a 'collection' attribute.
In the Backbone source code, we have :
var Model = Backbone.Model = function(attributes, options) {
...
if (options && options.collection) this.collection = options.collection;
...
}
The annotated source says nothing about that, and the documentation references only functions.
I guess it's mainly used when deleting the model : the collection removes this model.
But what if the model belongs to many collections ? Is there a danger to use/override this collection attribute ?
It's used in two places (look a bit further down in the annotated source).
As you note, it's used when a model is destroyed, to remove the model from the collection.
Optimistically removes the model from its collection, if it has one.
In the url function, if the collection exists with a URL scheme, it uses that to construct a URL for the model.
if you're using Backbone's restful methods, override this to change the endpoint that will be called.