Will calling fetch on my Collection instantiate all of the Models it receives in Backbone? - backbone.js

I have this code in my Backbone application:
app.Collections.quotes = new app.Collections.Quotes();
app.Collections.quotes.fetch();
And I can see an array of Objects returned in the network tab but when I expand out the Collection, the Models array inside is 0. Do they get instantiated as Models when fetch() is ran on a new Collection?
This is my Collection:
app.Collections.Quotes = Backbone.Collection.extend({
model: app.Models.Quote,
url: function() {
return app.Settings.apiUrl() + '/quotes';
}
});
EDIT:
app.Collections.quotes.fetch({
success: function(){
app.Utils.ViewManager.swap('section', new app.Views.section({section: 'quotes'}));
}
});
And in my Model:
idAttribute: 'Number',
This was the fix! Thanks for help. Dan kinda pointed me in the right direction amongst the comments...

Calling fetch() on a Collection attempts to populate the JSON response into Models: Collection#fetch.
Is your server definitely returning a valid JSON array of objects?
Do you have any validation on your Quote Model? I'm pretty sure Backbone validates each models before populating the collection, only populating with the models which pass. So if it exists, check that your Model#validate method is working correctly.
You shouldn't need an ID (although it's obviously required if you want to edit them).

Related

Backbone Collection get property

Got a server returning a JSON object like so:
{
'key1':'value'
'key2':{
'key2_0':'value'
}
}
And a collection:
var Collection = Backbone.Collection.extend({
url:api.url//which returns the object above
});
var collection = new Collection();
collection.fetch({
success:function(data){
//do something
}
});
Now i need to use certain properties of the collection throughout my application, but say i need key1, i always have to do collection.at(0).get('key1');//returns 'value', because the data returned is stored within the collection, in a new Array at key 0.
Question:
How to directly... collection.get('key1')//now returns undefined... because it is.
I know i could expose an object to the global scope in the collection success function some_other_var = data.toJSON()[0] and access the some_other_var properties directly, but that's not what i'm looking for;
In order to use the get() function from a Backbone.Collection you need to know the model id or cid wanted.
For instance, lets say your data coming from the server is like follow:
[{
id: '123',
name: 'Alex'
}, {
id: '456',
name: 'Jhon'
}]
In that case you can do this:
this.collection.get('123').get('name') // Return "Alex"
Keep in mind that collection is just a set of model, so behind the scenes by doing collection.get() you are getting a model
Tip: If you don't have any kind of id in your server data, there is always the option of using underscore methods:
find
filter
some
contains
etc
It seems like you're trying to ascribe attributes to a collection, but a collection is merely a set of models. Having additional data that is constant throughout the collection suggests that it should be wrapped inside another Model, which is demonstrated here: Persisting & loading metadata in a backbone.js collection

Backbone model structure gets changed when returning them from web worker

I am trying to reset a backbone collection with an array of models. It gets reset but the model structure is changed (nested one level).
Here is a detailed explanation:
Model
var SeatModel = Backbone.Model.extend({
defaults:{
},
initialize:function () {
console.log('Model initialized');
}
});
Collection
var myCollection = Backbone.Collection.extend({
url:"",
parse:function (data) {
},
initialize:function () {
console.log('Collection initialized');
}
});
Now, I am executing some logic in a web worker, which generates an array of models. The size of the array varies depending on the url I hit.
When the array is ready, I reset the data in the collection using something like:
(Before this, I have instantiated the collection and set it in an service object)
worker.onmessage = function(e) {
newDataForCollection = e.data;
//update the collection
service.get("myCollection").reset(newDataForCollection);
};
After getting reset, the structure of the collection gets changed to something like:
models: Array[3154]
[0...99]
0:g.Model
attributes:
attributes:
price: "12"
Whereas it should be like:
models: Array[3154]
[0...99]
0:g.Model
attributes:
price: "12"
Also the number of models in the array gets reduced. (Should have been around 6100 in this case).
I am unable to figure out, what causes the internal structure to get nested by one level on invoking reset on the collection.
Updated Post
Figured it out. We cannot send objects with functions in post message, so the models in the array just have the attributes and no functions. Related Passing objects to a web worker
Figured it out. We cannot send objects with functions in post message, so the models in the array just have the attributes and no functions. This was related to issue Passing objects to a web worker

backbone.js modify specific fields of model after fetch the collection

var items=[{"endsAt": "2013-05-26T07:00:00Z","id": 1,"name": "Niuniu1"},
{"endsAt": "2013-05-26T07:00:00Z","id": 2,"name": "Niuniu2"}]
ItemModel=Backbone.Model.extend({});
ItemCollection=Backbone.Collection.extend({
model:ItemModel,
url: '...',
parse: function(response) {
return response.items;
}
})
If I have a series of data like items, when I build model, for each model, it's endAt will be "2013-05-26T07:00:00Z". Where can I modify the model or data process so it will actually be "2013-05-26"?
I could do a foreach loop inside collection to process the date, but I'm wondering if there is a better pracitce like to do a parse inside the model?
Thanks!
The practice I use is the one you said you've thought about - implementing a custom parse on the model. As the documentation states, it will be called for you after a sync. See here: http://backbonejs.org/#Model-parse
ItemModel = Backbone.Model.extend({
parse: function(response,options) {
//perform your work on 'response',
// return the attributes this model should have.
};
})
As far as I know, you have 2 options here
Implement a custom parse method inside your model
Implement the initialize method inside your model
Both of them don't have any problems, I did 2 ways in several projects, and they work well

backbone.js dry search results model and collection

I'm trying to create a dry search results model and collection for backbone so that no matter what I'm searching for in the app, we use the same model/collection and occasionally might call a different view.
My Model and controller are very simple
Myapp.Models.Search = Backbone.Model.extend();
Myapp.Collections.Search = Backbone.Collection.extend({
model: Myapp.Models.Search
});
I then populate the url value to get the correct requests and parameters in the view
Myapp.Views.SearchResults = Backbone.View.extend({
el: 'div#results',
initialize: function(){
Myapp.results = new Backbone.Collection.Search;
Myapp.results.url = this.model.search_type+'/'+this.model.data; //this holds the search query
Myapp.results.fetch({
success: function(){alert('got result')},
error: function(){alert('that is not good!');}
});
}
without 'fetch', everything is fine, but when I include fetch, the fetch is made, the results are returned, but I get the error
Uncaught TypeError: undefined is not a function in backbone.js:23
I've checked the response, and it is valid JSON. When I output the Myapp.results to the console, I see the collection, but it is still empty. Neither the error not success are getting gtriggered.
----------------update------------------------
as per the comments, I've divided up line 23, and found that the error is being returned in this line
a=new this.model(a,b),
If I am understanding what this line does, could this issue be because the response collection only has one model being returned? I would hope that wouldn't cause the issue, you should be able to have a collection with 1 or less models in it.
--------------update--------------------------
So I remove the reference to model within the collection, and now I don't get the error. So in some ways, this is resolved, but it shouldn't be. Is there a reason why up to now I've always defined the model associated with the collection?

Uncaught Error: A "url" property or function must be specified for a CollectionView

I know this error has come up a few times, but I'm still not sure how to make this work appropriately..
My magic begins here :
var list_edit_member_view = new app.views.ListMemberEdit({
el: $("#enterprise_member_list_edit_container"),
list_ids: list_ids
});
list_edit_member_view.render();
And this loads this View (ListMemberEdit.js) which has this in the render() :
this.list_edit_member_view = new app.views.CollectionView({
el: $("#enterprise_member_list_edit_container"),
collection: app.peers,
list_item: app.views.ListMemberEditSelection,
list_item_options: {list_ids: this.options.list_ids}
});
Which loads a CollectionView view that renders its list_item_options as model views.. It is within this file (ListMemberEditSelection.js), that when I perform this.destroy, it will return :
Uncaught Error: A "url" property or function must be specified
So this makes me think that the Model or the Model URL is not being defined.. I'm just not sure where to put this since it works very similar to my other partials that are doing roughly the same thing..
Any thoughts? My apologies for the vagueness. Let me know if there's anything else you would like to look at!
I'm curious if its possible to see where this URL attribute would be written within the Object Model or Collection itself.
This is because destroy() function will call Backbone.sync to update the server too, not only your models in the frontend. http://backbonejs.org/#Model-destroy
So, if you're using REST to sync your data, you'll need to set a url property in your model so Backbone know where to send request:
Backbone.Model.extend({
url: "http://myapi.com/"
})
To allow more flexibility, you can also set a urlRoot: http://backbonejs.org/#Model-urlRoot
I had a similar problem, I removed the "id":"" from my models default values and the problem was solved.
I did receive similar error
Try this: I am just making an assumption what your model might look like
window.MyModel = Backbone.Model.extend({
url: function(){
return this.instanceUrl;
},
initialize: function(props){
this.instanceUrl = props.url;
}
}
Please look at this question that I had posted myself for more details: https://stackoverflow.com/a/11700275/405117
I am providing this reference as the answers here helped me better understand
Hope this helps!

Resources