Model fetch including model as attribute in backbone - backbone.js

Here is the test code:
var Stat = Backbone.Model.extend({
defaults: {
power: 0,
speed: 1
}
});
var Player = Backbone.Model.extend({
defaults: {
name: "Igor",
surname: "Ola",
stats: null
},
urlRoot: "/cgi-bin/test.pl"
});
var player = null;
$(document).ready(function(){
player = new Player();
player.set("stats", new Stat());
player.fetch({
success: function() {
var text = player.get("stats").get("power");
console.log(text);
}
});
});
What I expect is that backbone would update the player model and it's stats attribute, which itself is another model (Stat).
But it doesn't work. Is there a way to do it? The goal is to update such a model in one fetch.
The player.get("stats") returns just an object, not Stat Model instance.

Related

change backbone model on the fly

I have a list models like Product, Book, Phone some of them may inherit from another.
And I try to build a from to add different products, the form view should be changed according to the type chosen by user.
This is what have tried now:
var Product = Backbone.Model.extend({
defaults: {
name: null,
price: 0,
type: null, /** phone or book or something else*/
phoneColor: null,
phoneWeight: 0,
bookCategory: null,
bookAuthor: null
}
});
var ProductFormView = Backbone.View.extend({
..........
render: function () {
var type = this.model.get('type');
switch (type) {
case 'phone':............
break;
case 'book':.........
break;
}
return this;
}
});
Put all the attributes to the Product, and render the form according to different model type, live demo: http://jsfiddle.net/57ra37vg/
Even it works now, but I think this is a bad idea, in my opinion, the base class Product should not contain too many attributes. I'd like something like this:
var Product = Backbone.Model.extend({
defaults: {
name: null,
price: 0,
type: null, /** phone or book or something else*/
}
});
var Book = Product.extend({
defaults:{
bookAuthor:null,
bookCategory:null
}
});
var ProductView = Backbone.View.extend({
render:function(){}
});
var BookView = ProductView.extend({
render:function(){}
});
var PhoneView = ProductView.extend({
render:function(){}
});
Each sub product owns their attributes and views. With this kind of design, when user change the type of the product by select an option, if I can change the current model to another kind of model, then refresh the view.
But it seems that I can not change a instance of Book to Phone on the fly.
So how do you make the design?
It is good to have separate View and Model. In this problem, we can have FormView, which can contain product view. Instead of changing the model on the fly, every product view can have their model. I would go with this design.
var Product = Backbone.Model.extend({
defaults: {
name: null,
price: 0
}
});
var Book = Product.extend({
defaults:{
bookAuthor:null,
bookCategory:null
}
});
var Phone = Product.extend({
defaults:{
color:null,
weight:null
}
});
var ProductView = Backbone.View.extend({
render:function(){}
});
var BookView = ProductView.extend({
initialize: function(options) {
this.model = new Book(options);
},
render:function(){}
});
var PhoneView = ProductView.extend({
initialize: function(options) {
this.model = new Phone(options);
},
render:function(){}
});
var FormView = Backbone.View.extend({
tagName: 'form',
defaults: {
productView: null
},
events: {
'change select': 'type_change'
},
type_change: function () {
var productType = this.$el.find('select').val()
this.productView.remove();
this.productView = this.getProductView(productType);
this.productView.render();
},
getProductView(product) {
if(product == "book")
return new ProductView();
return new BookView();
}
});

Appending data to same collection after every pagination fetch

I am trying to populate instagram images using backbone,
I have basically 3 models as follows,
User model store all the user info related to instagram
App.Models.User = Backbone.Model.extend({
defaults: {
id: '',
access_token: '',
userid: '',
username: '',
full_name: '',
profile_picture: ''
},
urlRoot: "/api/user/",
initurl: function() {
return "https://api.instagram.com/v1/users/"+this.get('userid')+"/media/recent/?access_token=" + this.get('access_token');
},
initialize: function() {
this.set('id', $('#domdump .id').val());
this.fetch({
success: function(model) {
var photos = new App.Collections.Ig_photos([],{
url: model.initurl()
});
}
});
}
});
A model to store the next url for pagination
App.Models.Ig_next_url = Backbone.Model.extend({
defaults: {
next_url: ''
},
next_url:function(){
return this.get('next_url');
}
});
A model for the photo
App.Models.Ig_photo = Backbone.Model.extend({});
A collection for the multiple photo
App.Collections.Ig_photos = Backbone.Collection.extend({
model: App.Models.Ig_photo,
initialize: function(model, options) {
this.url = options.url;
this.nextSet();
},
sync: sync_jsonp,
parse: function( response ) {
if(response.pagination && response.pagination.next_url && response.pagination.next_url != this.url){
var next_url = new App.Models.Ig_next_url({ next_url: response.pagination.next_url });
this.url = next_url.next_url();
}
return response.data;
},
nextSet: function(){
this.fetch({
success: function(photos){
var ig_photos_views = new App.Views.Ig_photos_view({ collection: photos});
console.log(photos);
}
});
}
});
Also i have some views that does the render with a load more button that calls the nextset of the collection.
What i was trying to achieve is the photos get appended to the collection upon nextset() and the collection get updated with pervious data + new data but right now its getting overwritten.
Also is it okay to instantiate new collection from the modelfetch ?
You shouldn't need to make a new view. You should instead listen to the "add" event being triggered on the collection and render new items accordingly.
nextSet: function(){
this.fetch({add : true}); // The add option appends to the collection
}
This option is detailed in the very good documentation.

Backbone - get method not returning the out put

i am new to Backbone.js, i have a data set, assigned to view, but i can't get the data, while i console that any one tell me what is wrong with my code?
code:
var model = Backbone.Model.extend({
data:[
{text:'Google',href:"http://www.google.com"},
{text:'Yahoo',href:"http://www.yahoo.com"},
{text:'Bing',href:"http://www.bing.com"}
]
});
var View = Backbone.View.extend({
initialize:function(){
this.render();
},
render:function(){
var data = this.model.get('data');
console.log(data);
}
});
var myView = new View({model:model});
the error i am getting is here:
TypeError: this.model.get is not a function
[Break On This Error]
var data = this.model.get('data');
You need to actually instantiate the model; using extend just creates an extension of the Backbone.Model prototype. The following creates a new instance of Backbone.Model, and initializes it with the data:
var model = new Backbone.Model({
data:[
{text:'Google',href:"http://www.google.com"},
{text:'Yahoo',href:"http://www.yahoo.com"},
{text:'Bing',href:"http://www.bing.com"}
]
});
var myView = new View({ model: model });
If you want to put the data in the type of the model itself, then you could use the defaults property:
var Model = Backbone.Model.extend({
defaults: {
data:[
{text:'Google',href:"http://www.google.com"},
{text:'Yahoo',href:"http://www.yahoo.com"},
{text:'Bing',href:"http://www.bing.com"}
]
}
});
var model = new Model();
var myView = new View({ model: model });

Backbone/Underscore uniqueId() Odd Numbers

I'm relatively new to Backbone and Underscore and have one of those questions that's not really an issue - just bugging me out of curiosity.
I built a very simple app that allows you to add and remove models within a collection and renders them in the browser. It also has the ability to console.log the collection (so I can see my collection).
Here's the weird thing: the ID's being generated are 1,3,5... and so on. Is there a reason specific to my code, or something to do with BB/US?
Here's a working Fiddle: http://jsfiddle.net/ptagp/
And the code:
App = (function(){
var AppModel = Backbone.Model.extend({
defaults: {
id: null,
item: null
}
});
var AppCollection = Backbone.Collection.extend({
model: AppModel
});
var AppView = Backbone.View.extend({
el: $('#app'),
newfield: $('#new-item'),
initialize: function(){
this.el = $(this.el);
},
events: {
'click #add-new': 'addItem',
'click .remove-item': 'removeItem',
'click #print-collection': 'printCollection'
},
template: $('#item-template').html(),
render: function(model){
var templ = _.template(this.template);
this.el.append(templ({
id: model.get('id'),
item: model.get('item')
}));
},
addItem: function(){
var NewModel = new AppModel({
id: _.uniqueId(),
item: this.newfield.val()
});
this.collection.add(NewModel);
this.render(NewModel);
},
removeItem: function(e){
var id = this.$(e.currentTarget).parent('div').data('id');
var model = this.collection.get(id);
this.collection.remove(model);
$(e.target).parent('div').remove();
},
printCollection: function(){
this.collection.each(function(model){
console.log(model.get('id')+': '+model.get('item'));
});
}
});
return {
start: function(){
new AppView({
collection: new AppCollection()
});
}
};
});
$(function(){ new App().start(); });
if you look in the backbone.js source code you'll notice that _.uniqueId is used to set a model's cid:
https://github.com/documentcloud/backbone/blob/master/backbone.js#L194
that means that every time you create a model instance, _.uniqueId() is invoked.
that's what causing it to increment twice.

Fetching data from model with backbone posts wierd parameters

I have created a model and collection like this:
var TestModel = Backbone.Model.extend({
initialize: function () {
},
defaults: {
'id': null,
'title': '',
'description': ''
}
});
TestCollection = Backbone.Collection.extend({
model: TestModel,
url: function () {
return 'Test/GetAll';
},
});
I then have a view I try to load like this:
var testCollection = new TestCollection();
var testListView = new TestListView({ collection: testCollection });
testCollection.fetch();
But it creates a request like:
Test/GetAll?_=1349272902901 which fails. Do any of you know why it appends this id-like parameter to the request?
Try:
testCollection.fetch({ cache: false });

Resources