I want to pass an array to a view like this
this.account_nav = new AccountNav.View({
views: [
{ ref: new Member.Views.AccountNav({ model: this.model }), id: 'viewA' },
{ ref: new Member.Views.SettingsNav({ model: this.model}), id: 'viewB' }
]
});
However there is an error:
Uncaught Error: The argument associated with selector '' is defined
and a View. Set manage property to true for Backbone.View
instances. backbone.layoutmanager.js:208
pointing to
this.account_nav = new AccountNav.View({
Any ideas why I get this error?
If your View definition is created using Backbone.Layout.extend rather than Backbone.View.extend, this issue shouldn't arise.
To cite the Layout Manager documentation example:
var LoginView = Backbone.Layout.extend({
template: "#login-template"
});
versus
var LoginView = Backbone.View.extend({
// [...]
});
https://github.com/tbranyen/backbone.layoutmanager/wiki/Example-usage#structuring-a-view
Related
I'm new to backbone.js and have inherited some code with a collection defined inside a method within a view. I would like to pull it out into its own module but am struggling. Here is the collection:
ResourceCollection = AbstractCollection.extend({
url: url,
model: ResourceModel,
state: state,
queryParams: BackgridUtils.getQueryParams({
_queryFilter: 'true'
}, this.data.isSystemResource)
});
this.model.resources = new ResourceCollection();
And here is what the refactored module looks like so far:
define("resource/ResourceCollection", [
"underscore",
"main/AbstractCollection",
"util/BackgridUtils"
], function(_, AbstractCollection, BackgridUtils) {
var ResourceCollection = AbstractCollection.extend({
url: url,
model: ResourceModel,
state: state,
queryParams: BackgridUtils.getQueryParams({
_queryFilter: 'true'
}, this.data.isSystemResource)
});
return new ResourceCollection;
});
How can I instantiate the collection from my view with the proper values? Thanks in advance.
You should return the actual constructor of the collection rather than just an instance of it.
Then you can use this "module" to create instances of this collection anywhere else in your application.
define("resource/ResourceCollection", [
"underscore",
"main/AbstractCollection",
"util/BackgridUtils"
], function(_, AbstractCollection, BackgridUtils) {
var ResourceCollection = AbstractCollection.extend({
url: url,
model: ResourceModel,
initialize: function(models,options){
//handle custome options here
},
state: state,
queryParams: BackgridUtils.getQueryParams({
_queryFilter: 'true'
}, this.data.isSystemResource)
});
return ResourceCollection;
});
Then from your view you can create instances of your collection with dynamic data like
new ResourceCollection([],{
url: "some dynamic url"
//some other custom options can be passed here
})
Model code:
App.Team = Backbone.RelationalModel.extend({
urlRoot: 'data/json/team',
/*urlRoot: 'data/json/myteam.txt',*/
idAttribute: 'id',
relations:
...
app.currentTeam = new App.Team({id:11});
View:
var trophiesBox = JST['teaminfo/history/leftbox'](app.currentTeam.attributes);
$("#teamhistory_leftbox").append(trophiesBox);
for (var i = 1; i <= app.currentTeam.attributes.history.length; i++) {
var historyData = app.currentTeam.attributes.history.get(i);
var historyRow = JST['teaminfo/history/row'] (historyData.attributes);
$("#teamhistory_table_body").append(historyRow);
}
I'm getting "Uncaught TypeError: Cannot read property 'attributes' of undefined"
on var historyRow = JST['teaminfo/history/row'] (historyData.attributes); line.
Before I had problems defining historyData, probably since it is a model in a collection (app.currentTeam.attributes.history) inside of another model (app.currentTeam). I was getting [Object] (app.currentTeam.attributes.history) doesn't have a 'get' method type of error. Now it passes fine, but I get another error message in the next line, so I wonder what is wrong with my code here.
app.currentTeam.attributes loads fine, so I guess there is a problem retrieving attributes of a model that is inside a collection within another model.
Edit: relation of Team and History collection:
{
type: Backbone.HasMany,
key: 'history',
relatedModel: 'App.HistoryItem',
collectionType: 'App.History',
reverseRelation: {
key: 'team',
includeInJSON: 'id',
}
}
You get Model from Collection from wrong method
app.currentTeam.attributes.history.get(i);
You have to use
app.currentTeam.get('history') // you got collection
app.currentTeam.get('history').at(i); // you got model from collection by index
Update1:
Try use iterator for get elements from collection:
var trophiesBox = JST['teaminfo/history/leftbox'](app.currentTeam.attributes);
$("#teamhistory_leftbox").append(trophiesBox);
app.currentTeam.get('history').each(function(historyData, i) {
var historyRow = JST['teaminfo/history/row'](historyData.attributes);
$("#teamhistory_table_body").append(historyRow);
}, this);
Have you checked Backbone Associations. This might be of some help.
Two common scenarios when I am using backbone backbone:
Attribute is listed as default value, then set
modelExample_A: Backbone.Model.extend({
defaults: {
whatever: 'foo'
something: 'blah'
}
});
viewExample_A: Backbone.View.extend({
//our view definition
});
var Example_A = new viewExample_A({
model: new modelExample_A()
})
Example_A.set({
'whatever': 'bar',
'something': 'weeeeeee',
});
Attribute is not listed as a default value, then set
modelExample_A: Backbone.Model.extend({
});
viewExample_A: Backbone.View.extend({
//our view definition
});
var Example_A = new viewExample_A({
model: new modelExample_A()
})
Example_A.set({
'whatever': 'bar',
'something': 'weeeeeee',
});
Attribute is not listed as a default value, set on creation
modelExample_A: Backbone.Model.extend({
});
viewExample_A: Backbone.View.extend({
//our view definition
});
var Example_A = new viewExample_A({
model: new modelExample_A({
'whatever': 'bar',
'something': 'weeeeeee',
})
})
But what about situations where I want to set a property of the model? I know this is generally discouraged, but sometimes in my code I like to make a not of a what model is the parent of the current model. This is something that almost certainly won't ever change, so there is no reason to put in the attribute for event listening/onChange purposes. Further, this is something without a default value (it can only get a value in context), so is it okay to just set it as a property of the model? Or will this cause problems down the line?
Setting a property instead of an attribute
modelExample_A: Backbone.Model.extend({
defaults: {
whatever: 'foo'
something: 'blah'
}
});
viewExample_A: Backbone.View.extend({
//our view definition
});
var Example_A = new viewExample_A({
model: new modelExample_A({
'whatever': 'bar',
'something': 'weeeeeee',
})
})
Example_A.parentModel = parentModelExample;
Used in moderation and with consideration, setting non-attribute properties on model instances is fine. Just be careful not to have this be data that can easily get into an inconsistent state, and if you are doing this a lot, that's a code smell. In that case, you may want to consider modeling some state as actual models with attributes, but just not persisting them (never call .save).
backbone Model,board:
define([
'underscore',
'backbone',
'collections/lists',
'iobind',
'iosync'
], function( _, Backbone, Lists,ioBind,ioSync) {
var BoardModel = Backbone.Model.extend({
urlRoot: 'board',
noIoBind: false,
socket: io.connect(''),
idAttribute: '_id',
defaults: {
title: 'One Thousand and One Nights'
},
initialize: function() {
this.id = 1;
this.lists = new Lists;
this.socket.emit('joinBoard',this.id);
_.bindAll(this, 'getBoard');
this.ioBind('initBoard', this.getBoard, this);
},
getBoard: function(data){
this.set(data.data.board[0]);
}
});
return BoardModel;
});
backbone View: boardView:
var IndexView = Backbone.View.extend({
// Instead of generating a new element, bind to the existing elements in the HTML.
el: '#board',
// Board template html
template: Mustache.render(Template.board),
events: {
},
initialize: function() {
//Init Data
this.model = new Board();
// var lists = {
// lists: [
// {name: "To Do",
// cards:[
// {name: "Art work for A."},
// {name: "B Prototype."},
// {name: "C prototype."}
// ]
// },
// {name: "Doing",
// cards: [
// {name: "Art work for A."}
// ]
// },
// {name: "Done"}
// ]
// }
// var partial = {card: Template.card_in_list};
// var listHtml = Mustache.render(Template.list,lists,partial);
// template = $(this.template).find('.list-area').append(listHtml);
},
render: function() {
console.log(this.model);
console.log(this.model.toJSON());
var partial = {card: Template.card_in_list};
var listHtml = Mustache.render(Template.list,this.model,partial);
template = $(this.template).find('.list-area').append(listHtml);
this.$el.html(template);
}
});
in View function: render function, the console.log get different result.
console.log(this.model) can get correct object result:
child
_callbacks: Object
_changing: false
_escapedAttributes: Object
_ioEvents: Object
_pending: Object
_previousAttributes: Object
_silent: Object
attributes: Object
__v: 0
_id: "50b750a7795f285d4e000014"
created: "2012-11-29T12:10:15.269Z"
description: "simple is better, but not simpler"
dueDate: "2012-11-29T12:10:15.269Z"
lists: Array[6]
status: true
title: "test board unique"
__proto__: Object
changed: Object
cid: "c1"
getBoard: function () { [native code] }
id: "50b750a7795f285d4e000014"
lists: child
__proto__: ctor
but this.model.toJSON() only get model default values:
Object
title: "One Thousand and One Nights"
__proto__: Object
it confuse me. anyone know why reason the same model get different result.
In a Backbone Model, your business values (description, title ...) are store in the attributes attribute. When you call toJSON() on your model, what it does is it takes the attributes values, and remove the Backbone.Model object framework's functions and attributes.
When you manually want to set model attributes, you want to use set. I don't know what is in you data.data object, so you should check the doc : http://backbonejs.org/#Model-set
set model.set(attributes, [options])
Set a hash of attributes (one or
many) on the model. If any of the attributes change the models state,
a "change" event will be triggered, unless {silent: true} is passed as
an option. Change events for specific attributes are also triggered,
and you can bind to those as well, for example: change:title, and
change:content. You may also pass individual keys and values.
note.set({title: "March 20", content: "In his eyes she eclipses..."});
book.set("title", "A Scandal in Bohemia"); If the model has a validate
method, it will be validated before the attributes are set, no changes
will occur if the validation fails, and set will return false.
Otherwise, set returns a reference to the model. You may also pass an
error callback in the options, which will be invoked instead of
triggering an "error" event, should validation fail. If {silent: true}
is passed as an option, the validation is deferred until the next
change.
I found i trigger boardView.render twice. when i change code:
a = new boardView;
a.render();
to
a = new boardView;
i got the thing done.
by the way thanks Marcel Falliere's comments.
I am very new to Backbone and am doing a simple tutorial. I keep running into an error that I dont understand. Here is my code.
(function($) {
dataModel = new Backbone.Model.extend({
data: [
{text: "Google", href: "www.google.com"},
{text: "Yahoo", href: "www.yahoo.com"},
{text: "Youtube", href: "www.youtube.com"},
]
});
var View = Backbone.View.extend({
initialize: function(){
this.template = $('#list-template').children();
},
el: $('#container'),
events: {
"click button": "render"
},
render: function(){
var data = this.model.get('data');
for(var i = 0, l = data.length; i < l; i++){
var li = this.template.clone().find('a').attr('href', data[i].href).text(data[i].text).end();
this.el.find('ul').append(li);
}
}
});
var view = new View({ model: dataModel });
})(jQuery);
When I call this.model.get('data') I get the error TypeError: Object function (){return a.apply(this,arguments)} has no method 'get'. Please show me my error. Thanks.
All the properties and methods you pass when extending a model are set on its prototype not as its attributes, and dataModel here is not a Backbone model instance but a Backbone Model subclass. If done this way to access the data property you'd need to instantiate the model and do a modelInstance.data rather then modelInstance.get('data') as if it would be when data would be set as model attribute as shown in the example below.
What you wanted to do here was
var dataModel = new Backbone.Model({ // without the extend!
data: [
{text: "Google", href: "www.google.com"},
{text: "Yahoo", href: "www.yahoo.com"},
{text: "Youtube", href: "www.youtube.com"},
]
});
as you want to create an instance of a model rather then subclass Backbone.Model class. Extend method is used to subclass core Backbone classes – views, models, collections and routers.
Your 'dataModel' is just the definition of the Model. You need to create a model instance by calling new dataModel() when you pass it to the view.
a model define`s only the structure of one data element
Model
defaults:
text : null
href : null
what you need is a Collection
Collection
model : Model
you can then set data to the collection with .add
Collection.add([
{text: "Google", href: "www.google.com"},
{text: "Yahoo", href: "www.yahoo.com"},
{text: "Youtube", href: "www.youtube.com"},
])
to get the data from the collection look here
http://underscorejs.org/#collections
Hope it helps