Backbone Nested Collections - javascript

i'm trying to populate a nested collection that's inside a model, and taht last model inside another collection.
The code is the following
App.Models.Bed = Backbone.Model.extend();
App.Collections.Beds = Backbone.Collection.extend({
model: App.Models.Bed,
initialize: function(models, options){
this.room = options.room;
}
});
App.Models.Room = Backbone.Model.extend();
App.Collections.Room = Backbone.Collection.extend({
url: 'rooms/',
initialize: function(){
this.on('reset', this.getBeds, this);
},
getBeds: function(){
this.each(function( room ){
room.beds = new App.Collections.Beds([], { room: room});
room.beds.url = 'rooms/' + room.id + '/beds';
room.beds.fetch();
console.log(room.beds.toJSON());
});
}
});
Now, if I execute:
var rooms = new App.Collections.Room();
rooms.fetch();
rooms.toJSON();
It gives me back just the rooms populated, but no beds property on each bed.
The wired thing is that it makes the request to the server at /rooms/1/beds and I get back each bed.
Is it populating the beds collection?
Am I doing something wrong?
Thanks for your time mates.

Looks like you need to pass in the Room Model to the Room Collections.

Related

backbonejs - accessing collection in view

backbonejs and oop js newbie here. i am trying to bind my collection to a view, when i go to my console, i only get this
this is a collection: [object Object]
is there something am i missing here?
var root = "http://jsonplaceholder.typicode.com";
var Post = Backbone.Model.extend({});
var Posts = Backbone.Collection.extend({
model: Post,
url: root + "/posts",
parse: function(response) {
return response;
}
});
var posts = new Posts();
posts.fetch();
// View wrapper to render view child items
var PostsView = Backbone.View.extend({
collection: new Posts(),
initialize: function() {
console.log('this is a collection: ' + this.collection);
},
render: function() {
// STEPS:
// filter through all items in a collection
// for each item, create a new PostView
// append to root element, ex. ul
}
});
var postsview = new PostsView();
When you do 'this is a collection: ' + this.collection you're forcing the collection to be a string, and javascript sees an object and turns it into your [object Object].
The correct way to show a collection as a string is to just its .toJSON() function and do console.log('this is a collection: ' + JSON.stringify(this.collection.toJSON())); but since most devtools are capable of properly showing an object natively you're better off using
console.log('this is a collection: ', this.collection);
That should give you a nice interactive representation of the collection in your console, at least on Chrome.

Proper way of populating Backbone Collection

I have the following Backbone Model and Collection
/**
* DataPoint
*/
var DataPoint = Backbone.Model.extend({
defaults: {
ts: null,
value: null
}
});
var DataPointCollection = Backbone.Collection.extend({
model: DataPoint
});
In order to populate and do what I need to do with the data I do something similar to this:
url = '/api/v1/database/1/data';
$.getJSON(url, params, function(data) {
var dps = new DataPointCollection;
dps.add(data.datapoints);
//Now do stuff with dps
});
I'm sure there is a better way to do this with Backbone but not sure how. I feel it should be more like telling the DataPoint collection to populate itself.
How to approach this on backbone?
Have a look at the docs, fetch is what you're looking for; here's the example took from there:
var accounts = new Backbone.Collection;
accounts.url = '/accounts';
accounts.fetch();

How to extract a specific model from collection,and set id model

Goodmorning,i'm a bit confused about a specific id that a model has got and the id that it's has in parse.com because my collection is linked to parse.com.
If i want to get a specific model from my collection how can i do?
An example,my collection is this:
var Proposte = Backbone.Collection.extend({
model:Proposta,
url:'https://api.parse.com/1/classes/Proposte',
});
return Proposte;
and my model is this:
var Proposta = Backbone.Model.extend({
url:"https://api.parse.com/1/classes/Proposte",
...
If i want to get a specific model from my collection how can i do?
have a try at this:
var item = Proposte.findWhere({'url':"https://api.parse.com/1/classes/Proposte"});
hare is the doc
Edit:
The code above gives you the first matched model of the collection.
If you want to get multiple models that matches the specific attributes of a model, just use where
General case:
Define idAttribute for your Model/Collection:
var Proposta = Backbone.Model.extend({
idAttribute: 'name',
});
var Proposte = Backbone.Collection.extend({
model:Proposta,
url:'https://api.parse.com/1/classes/Proposte'
});
// Done here with static data just for illustration
var collection = new Proposte([{name: 'aaa'}, {name: 'bbb'}]);
Use the defined attribute to retrieve Models from collection:
console.log(collection.get('aaa'));
JSFIddle
URL, of course, can also be that attribute (just in case):
var Proposta = Backbone.Model.extend({
idAttribute: 'url'
});
var Proposte = Backbone.Collection.extend({
model:Proposta,
url:'https://api.parse.com/1/classes/Proposte',
});
var collection = new Proposte([{url: 'https://api.parse.com/1/classes/Proposte/1'}, {url: 'https://api.parse.com/1/classes/Proposte/2'}]);
console.log(collection.get('https://api.parse.com/1/classes/Proposte/2'));

populate collection on Backbone

Tutorial.Views.Layout = Backbone.Layout.extend({
model: Tutorial.Model,
});
initialize: function () {
_.bindAll(this);
this.model = new Tutorial.Model({id : $("#data").data('user') });
this.collection = new Tutorial.Collection();
var success1 = function(){
console.log('OK');
};
this.collection.fetch({success : success1});
},
showTuto: function(){
step = this.collection.first(1);
console.log(step);
},
My problem is my collection is empty. My model has 4 items, but i see none of them .
Thanks in advance
We need to see some more code to make a closer suggestion, but hopefully this explanation will help you out. You should pass your model directly to the collection, OR deal with it in the fetch.
//simplified view
YourView = Backbone.View.extend({
initialize : function(){
var testModel = new Tutorial.Model({id : $("#data").data('user') });
this.collection = new Tutorial.Collection();
this.collection.add(testModel);
}
});
In this case, you would be adding that model directly to your collection. If you want to asyncronously call and get data from the fetch and then pass a callback, you could do something like this:
//simplified view
YourView = Backbone.View.extend({
initialize : function(){
this.collection = new Tutorial.Collection();
this.collection.fetch(function(){
console.log('okay');
});
}
});
Tutorial.Collection = Backbone.Collection.extend({
fetch : function(callback){
// grab a ref to your collection
var thisCollection = this;
// call your data function which has the ajax call
getYourDataFunction(function(data){
// if your data returned is an array of objects
thisCollection.add(data);
if (typeof callback === "function"){
//if you included a callback, call it with a reference to the collection
callback.call(thisCollection);
}
});
});
});

How do I render multiple records out to a html table with Backbone.js ?

var ContractModel = Backbone.Model.extend({
url: "${g.createLink(controller:'waiverContract', action:'index')}"
})
var contract = new ContractModel({});
contract.fetch();
var contracts = new Backbone.Collection.extend({
model: contract
});
var ContractView = Backbone.View.extend({
initialize: function(){
this.render();
},
render: function() {
var root = this.$el;
_.each(this.model, function(item) {
var row = '<tr><td>' + item + '</td></tr>';
root.find('tbody').append(row);
});
return this;
}
});
var cView = new ContractView({ model: contract, el: $('#contracts') });
I have Chrome's developer tools open. If I do a console.log(this.model) inside of the render function, I can see a mess of an object, of which the two records are stored in .attributes. But instead of two rows being added to the table, I get 7. 6 of which are objects. (Though I see 9 subobjects in Chrome's console).
Not much of this makes sense to me. Can anyone help me not only get this working, but also understand it? I know that render() fires off as soon as I have instantiated cView, and I know that it's doing the ajax as soon as I do .fetch() into the model. But that's the limit of what I can understand in this.
You should fetch and iterate on the collection, not the model. A model is one "thing" and a collection has many "things". Assuming you are fetching a JSON formatted array into your model, it will end up with properties like "1", "2", and so on, and each of these will just be a normal Javascript object, not a ContractModel instance.
Here is how you might restructure your code:
var ContractModel = Backbone.Model.extend();
var ContractCollection = Backbone.Collection.extend({
//ContractModel class, not an instance
model: ContractModel,
//Set the url property on the collection, not the model
url: "${g.createLink(controller:'waiverContract', action:'index')}"
})
var ContractView = Backbone.View.extend({
initialize: function(){
//Bind the collection reset event, gets fired when fetch complets
this.collection.on('reset', this.render, this);
},
render: function() {
//This finds the tbody element scoped to your view.
//This assumes you have already added a tbody to the view somehow.
//You might do this with something like
//this.$el.html('<table><tbody></tbody></table>');
var $tbody = this.$('tbody');
this.collection.each(function(contract) {
//Add any other contract properties here,
//as needed, by calling the get() model method
var row = '<tr><td>' + contract.get('someContractProperty') + '</td></tr>';
//Append the row to the tbody
$tbody.append(row);
});
return this;
}
});
//Instantiate collection here, and pass it to the view
var contracts = new ContractCollection();
var cView = new ContractView({
collection: contracts,
el: $('#contracts')
});
//Makes the AJAX call.
//Triggers reset on success, and causes the view to render.
//Assumes a JSON response format like:
// [ { ... }, { ... }, ... ]
contracts.fetch();

Categories

Resources