Parent element for backbone view? - backbone.js

How set Parent element for backbone view ?
var TodosView = Backbone.View.extend({
tagName: 'p', // required, but defaults to 'div' if not set
className: 'container', // optional, you can assign multiple classes to
// this property like so: 'container homepage'
id: 'todos', // optional
initialize: function(){
// debugger
this.$el.html("bamboo4a")
$("body").append(this.$el);
}
});
var todosView = new TodosView();
I do not want to write $("body").append

For the main view you can set the view element when creating the view object by passing the options to its constructor (namely the option el).
var MyView = Backbone.View.extend({
template: '<p>Hello World!</p>',
render: function() {
this.$el.html(this.template);
}
});
new MyView({
el: 'body' // or el: '#content' and so on
}).render();
Documentation
Demo
Demo with more detailed example of the application

Related

Can't get Backbone Events to work

I'm using Backbone.js 1.1.2 with jQuery 1.11.
I think I'm missing something very simple.
I've set up a model: Contact and a collection: ContactList.
I have success rendering ContactView views with models obtained from ContactList.fetch()
But when I try to bind a change event in the view initializer:
this.model.on('change', this.render, this);
... I get:
backbone Uncaught TypeError: Object #<Object> has no method 'on'
So I go back to the documentation and read that .on() is part of Backbone.Events, and somehow I need to extend my model to use this (and why is this not part of the out-of-the-box functionality for models??)
I've tried declaring
_.extend(this, Backbone.Events);
... inside of the initialize function for ContactView before declaring the binding, but no dice.
What do I need to do to get the Backbone.Events functionality working??
update: all relevant code (sans template)
var Contact = Backbone.Model.extend({
defaults: {
FirstName: '',
...[etc]
},
initialize: function() {
}
});
var ContactList = Backbone.Collection.extend({
model: Contact,
url: '/api/Contacts/getall'
});
var ContactView = Backbone.View.extend({
initialize: function() {
this.render();
this.model.on('change', this.render, this);
},
render: function () {
var template = _.template($('#contact_template').html(), this.model);
this.$el.html(template);
}
});
var contactList = new ContactList();
contactList.fetch({
success: function (collection, response, options) {
contactList.models.forEach(function (m) {
var $el = $('<li />')
.addClass('adminItem clearfix')
.appendTo($('#contactList'));
new ContactView({ el: $el, model: m.attributes });
});
}
});
This line is the source of trouble
new ContactView({ el: $el, model: m.attributes });
m.attributes is a plain js object. You want to pass along the actual model object:
new ContactView({ el: $el, model: m});
And because the collection has underscore methods mixed in you should be able to simplify it a bit to this:
contactList.each(function (m) {
var $el = $('<li />')
.addClass('adminItem clearfix')
.appendTo($('#contactList'));
new ContactView({ el: $el, model: m});
});

getting model data to a view backbone.js

I am trying to understand the relationship between a model and a view. I've tried building a model and view to render that model.
I get the error Cannot call method 'toJSON' of undefined which I understand as the actual instance of the model is not being sent to the view.
I feel there is something missing in the initialize of the view?
The Model:
var sticky = Backbone.Model.extend({
defaults: {
title:"",
content:"",
created: new Date()
},
initialize: function() {
console.log("sticky created!");
}
});
The View:
var stickyView = Backbone.View.extend({
tagName:"div",
className:"sticky-container",
initialize: function() {
this.render();
console.log("stickyView created!");
},
render: function() {
$("#content-view").prepend(this.el);
var data = this.model.toJSON(); // Error: Cannot call method 'toJSON' of undefined
console.log(data);
var source = $("#sticky-template").html();
var template = Handlebars.compile(source);
$(this.el).html(template(data));
return this;
}
});
Creating new model and new instance of the view:
var Sticky = new sticky({title:"test"});
var StickyView = new stickyView();
You have to pass your model instance to your view, Backbone will do the rest:
constructor / initialize new View([options])
There are several special options that, if passed, will be attached directly to
the view: model, collection, el, id, className, tagName and
attributes.
which means you would create your view like this
var StickyView = new stickyView({model: Sticky});
And while you're at it, you could pass your compiled template and the DOM node you wish to set as your view element (and remove the tagName and className from your view definition) to avoid a strict coupling:
var stickyView = Backbone.View.extend({
initialize: function(opts) {
this.template = opts.template;
this.render();
console.log("stickyView created!");
},
render: function() {
var data = this.model.toJSON();
console.log(data);
this.$el.html(this.template(data));
return this;
}
});
var StickyView = new stickyView({
model: Sticky,
el: '#content-view',
template: Handlebars.compile($("#sticky-template").html())
});

backbone.js, connecting same collection model for 2 different views

I have a collection, and I'm trying to share information concerning the current model being selected between two different views
-->TO PUT IT SIMPLY, I WANT TO BE ABLE TO ACCESS THE MODEL SELECTED IN ONE VIEW FROM ANOTHER VIEW AND CHANGE/ASSIGN THE ATTRIBUTES OF THE MODEL
The first view is defined with:
App.Views.Person = Backbone.View.extend({
tagName: 'a',
template: template('personTemplate'),
initialize: function(){
this.model.on('change', this.render, this);
this.model.on('destroy', this.remove, this);
},
render: function() {
this.$el.html( this.template(this.model.toJSON()) );
this.input = this.$('.view');
return this;
},
the second view is defined with:
App.Views.App = Backbone.View.extend({
el: 'html',
initialize: function(){
_.bindAll(this,"render");
},
render: function() {
return this;
},
and I created my views with the following
addPersonView = new App.Views.AddPerson({ collection: peopleCollection });
appView = new App.Views.App({ model: person, collection: peopleCollection });
How do I make it so that the model selected in the 2nd view is the same as the model in the first view as pulled from my collection --> for example, when I type something into the input box on my bottom view, I want to be able to use: this.set.model({name:title}) and for this to set the model attribute for the element (associated with a model) that is selected in my top view, but using this.set.modelis not choosing the correct model that is selected in my first view
for further reference and confusion: my models are being added to my PeopleView with the following code which i'm loading from an array;
App.Views.People = Backbone.View.extend({
// tagName: '',
initialize: function() {
var i = 1;
while(i < size)
{
var person = new App.Models.Person({ url: jsArray[i] });// creating a new person object..
this.collection.add(person);
i++
}
this.collection.on('add', this.addOne, this);
console.log(jsArray[1]);
// listeners/anouncers for the collection on add..
},
// refactored render method...
render: function() {
this.collection.each(this.addOne, this);
return this;
},
// called from render method of collection view..
addOne: function(person) {
var personView = new App.Views.Person({ model: person, vent: vent });
this.$el.append(personView.render().el);
}
});
I resolved this by using 'vents' so to speak --> (awesome link) the vents provide ways for views to communicate etc
http://lostechies.com/derickbailey/2012/04/03/revisiting-the-backbone-event-aggregator-lessons-learned/, or an application level aggregator like so:
MyApp.vent = _.extend({}, Backbone.Events);
MyApp.vent.on("some:event", function(){
alert("some event was fired!");
});
MyApp.vent.trigger("some:event");

Super simple-minimal Backbone script requested

Looking for the absolute minimum script to get Backbone working. Tried piecing various tutorials and sample together, but having problems getting views to work. Nothing fancy, I'll take raw json in the browser right now. Just a basic skeleton to help connect the dots and build on. I've tried various variations on the following:
(function ($) {
var model = Backbone.Model.extend({
idAttribute: 'custId'
});
var collection = Backbone.Collection.extend({
initialize: function(){
},
model: model,
url: '/cust'
});
var view = Backbone.View.extend({
initialize: function(){
_.bindAll(this, 'render'); // fixes loss of context for 'this' within methods
this.collection.bind("reset", this.render);
this.render();
},
el: $('#content'),
template: Handlebars.compile($("#contentTemplate").html()),
render: function(){
$(this.el).html( this.template(this.model.toJSON()));
},
tagName: "li"
});
var router = Backbone.Router.extend({
initialize: function(){
var newCollection = new collection;
newCollection.fetch();
},
route: {
"": "home"
},
home: function(){
this.view = new view({collection: newCollection});
$('#content').html(this.view.el);
}
});
var app = new router();
}(jQuery))
Thanx.
You are misusing the el attribute. $('#content').html(this.view.el) will result in copying the $('#content') element inside itself (because view.el is equal to $('#content')).
You should try removing the el attribute from the view object and let it generate itself. Then $('#content').html(this.view.el); should work.
One other possible problem is that you are rendering the entire collection inside a li element - was this what you are going for? The best way to go about this would be to have each model in the collection represent a li tag and the collection a ul tag.
Other issues:
the view element is receiving a collection but you are trying to render a model
in the router, newCollection is not accessible in the home method
You are not calling Backbone.history.start()
Here is how i would rewrite the code:
var model = Backbone.Model.extend({
idAttribute: 'custId'
});
var model_view = Backbone.View.extend({
template: Handlebars.compile($("#modelTemplate").html()),
tagName: 'li',
initialize: function() {
_.bindAll(this, 'render');
this.render();
this.on('change',this.render);
},
render: function() {
$(this.el).html( this.template(this.model.toJSON()) );
return this;
}
});
var collection = Backbone.Collection.extend({
initialize: function(){
},
model: model,
url: '/cust'
});
var collection_view = Backbone.View.extend({
tagName: "ul",
initialize: function(){
_.bindAll(this, 'render','renderModels');
this.render();
this.renderModels();
this.collection.bind("reset", this.render);
this.collection.bind("reset", this.renderModels);
},
render: function(){
// just create the 'ul' tag; we will populate it with model view elements; a collection template is no longer needed
return this;
},
renderModels: function() {
this.collection.each(function(obj){
var view = new model_view({
model: obj
});
$(this.el).append(view.el);
},this);
}
});
var router = Backbone.Router.extend({
initialize: function(){
this.newCollection = new collection();
this.newCollection.fetch();
},
route: {
"": "home"
},
home: function(){
this.view = new collection_view({collection: this.newCollection});
$('#content').html(this.view.el); // #content should not be a 'ul' tag, the 'ul' is generated by the collection_view
}
});
var app = new router();
Backbone.history.start();
Make sure you update your templates accordingly.
Please excuse possible errors, i had no means to test the code but i believe it points out the logic you should use.
Cheers!

Backbone.js not rendering

My collection is not rendering for some reason. Cannot find out why.
TreeItem = Backbone.Model.extend({
});
TreeList = Backbone.Collection.extend({
model: TreeItem,
url: "/get_tree_list"
});
window.tree_list = new TreeList();
// VIEW
window.TreeItemView = Backbone.View.extend({
tagName: 'li',
initialize: function(){
_.bindAll(this, 'render');
},
render: function(){
$(this.el).html('<span>'+this.model.get('title')+'</span>');
return this;
}
});
window.TreeListView = Backbone.View.extend({
el: "#tree-structure",
events: {
},
initialize: function() {
_.bindAll(this, 'appendItem', 'render');
tree_list.bind('add', this.appendItem);
tree_list.fetch();
this.render();
},
render: function() {
tree_list.each(this.appendItem);
return this;
},
appendItem: function(item){
var tree_item_view = new TreeItemView({
model: item
});
$(this.el).append(tree_item_view.render().el);
}
});
var tree_list_view = new TreeListView;
Backbone.js provides a lot to be interpreted that's where people new go wrong. Your mistake is fundamental in nature. You tie the View directly to the model
see initialize function where a instance of collection is rendered!!
Always and anywhere you create model, collection pass then as parameters to the constructor of views. Check my fiddle
Never call render inside model, view or collection. They must be inside application file
JsFiddle
http://jsfiddle.net/35QGM/

Resources