Backbone.js basics: creating a view - backbone.js

I'm just starting to learn backbone.js. I'm following this tutorial here at backbonetutorials.com, but for some reason I'm not being able to put it working. Here's what I've got so far (fiddle):
var View = Backbone.View.extend({
el: $('.container'),
initialize: function() {
this.render();
},
render: function() {
var templ = _.template($('#template').html(), {});
this.el.html(templ);
},
events: {
"click button": "buttonClick"
},
buttonClick: function() {
alert('clicked!');
}
});
var view = new View();​
What's wrong with the above? I've almost just copy/pasted from the tutorial to the fiddle. Is it related to the backbone/underscore versions being used?
Thanks in advance.

try
this.$el.html(templ);
instead of
this.el.html(templ);
http://jsfiddle.net/eykKL/4/

Related

Variable passed into backbone view coming up undefined

I am in the process of learning backbone / underscore, and I am finding that the more I break away from the really basic stuff in the tutorials, the more come to realize that the tutorials aren't teaching me much of anything.
My current problem is with passing a variable to a view. I have three different templates available, but they all render the same, so I was hoping to just pass which template to use into the view when it was being rendered from the collection. What I thought would work would be just adding a property to the call to the view, and then accessing it with this.options.Property, but this is throwing an error that the property is undefined.
I have tried a number of variant options, but nothing seems to work. What am I doing wrong?
Thanks is advance.
var ProjectListView = Backbone.View.extend({
el: '#projectList',
initialize: function() {
this.collection = masterProjectList;
this.render();
},
render: function() {
this.$el.html("");
this.collection.each(function(project) {
this.renderItem(project);
}, this);
},
renderItem: function(project) {
var projectView = new ProjectView({model: project, projectType: '#theatricalProjectTemplate' });
// Passing in the project type, which determines which template gets used
this.$el.append(projectView.render().el);
}
});
var ProjectView = Backbone.View.extend({
tagName: "div",
className: "project-wrap",
template: _.template($(this.options.projectType).html()),
// use this.options to access the value
render: function() {
this.$el.html(this.template(this.model.toJSON()));
return this;
}
});
When you're defining your ProjectView:
var ProjectView = Backbone.View.extend({
//...
template: _.template($(this.options.projectType).html()),
//...
});
you're executing some code (i.e. calling extend) and in this context, this will be the global object (AKA window in a browser) and that probably won't have an options property. If you want to use the projectType option that you pass to the ProjectView constructor, move the template assignment into initialize:
var ProjectView = Backbone.View.extend({
tagName: "div",
className: "project-wrap",
initialize: function() {
this.template = _.template($(this.options.projectType).html());
},
render: function() {
this.$el.html(this.template(this.model.toJSON()));
return this;
}
});
This assumes that projectType will be a valid jQuery selector, you might want to use '#' + this.options.projectType instead but I'm not sure what exactly will be in projectType.
mu is too short is correct and if you define template method as follows, you can share the template method with all instances of ProjectView:
var ProjectView = Backbone.View.extend({
tagName: "div",
className: "project-wrap",
render: function() {
this.$el.html(this.template(this.model.toJSON()));
return this;
},
template: function() {
return _.template($(this.options.projectType).html());
}
});

edit - backbone.js beginner attempting to load data

Attempting to post a beginner question but not making it past the "quality standards" filter.
I read through the thread on the error message. Are beginner questions too basic? Understandable but it might be better to put that in the error message. I include my code and my English is correct outside of the code block. The question has not been addressed, or at least is not returned from various search patterns. Is there anyway to appeal the filter as multiple rewrites have not cleared the hurdle or solved my, admittedly beginner, problem? In a last ditch attempt to hack the filter I'm pasting my original question in bellow with a few English only edits. edit - this seems to have worked but leaving above paragraph in to not jinx it.
Trying to load data into backbone but the render function is not firing.
Firebug shows the GET is arriving with the correct data string.
I have attempted to assign "this" to a variable and fire as a function but still no luck.
(function($) {
var DObj = Backbone.Model.extend({
defaults: {
dstring: 'dstring again'
},
});
var MObs = Backbone.Collection.extend({
defaults: {
model: DObj
},
model: DObj,
url: 'scr/bbone.php'
});
var MView = Backbone.View.extend({
initialize: function() {
this.collection = new MObs();
//this.collection.bind("reset", this.render, this);
this.collection.on("sync", this.render, this);
//this.collection.bind("change", this.render, this);
this.collection.fetch();
},
render: function() {
alert("here : ");
}
});
var newMob = new MView();
})(jQuery);
I have rewritten the code with mockjax to mock response from the server, here it is:
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.4.4/underscore-min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/backbone.js/1.0.0/backbone-min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/jquery-mockjax/1.5.1/jquery.mockjax.min.js"></script>
<script>
var DObj = Backbone.Model.extend({
});
var MObs = Backbone.Collection.extend({
model: DObj,
url: '/movies'
});
$.mockjax({
type: 'GET',
url: '/movies',
contentType: 'text/json',
status: 200,
response: function() {
this.responseText = JSON.stringify(new MObs([{ name: 'Lincoln' }, { name: 'Argo' }]));
}
});
var MView = Backbone.View.extend({
initialize: function() {
this.collection.on("sync", this.render, this);
},
render: function() {
alert("here : ");
}
});
(function($) {
var newCol = new MObs();
newMob = new MView({ collection: newCol });
newCol.fetch({
success: function () { console.log('Success'); },
error: function() { console.log('Error'); }
});
})(jQuery);
I think there are many issues with code, the issue you were specifically asking for has to do with the server response; you should see an alert with the above code. I recommend you read backbone.js documentation for others.

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 and JQueryUI Dialog - events not binding

I'm trying to use Backbone.js to in a JQuery Dialog. I've managed to get the dialog to render and open, but it doesn't seem to be firing my events. I've added a test event to check this, and clicking it doesn't have the expected result.
I've tried following the instructions on this blogpost, regarding delegateEvents, but nothing it made no difference. No errors are thrown, the events just don't fire. Why is this?
Slx.Dialogs.NewBroadcastDialog.View = Backbone.View.extend({
events: {
"click .dialog-content": "clickTest"
},
clickTest : function () {
alert("click");
},
render: function () {
var compiledTemplate = Handlebars.compile(this.template);
var renderedContent = compiledTemplate();
var options = {
title: Slx.User.Language.dialog_title_new_message,
width: 500
};
$(renderedContent).dialog(options);
this.el = $("#newBroadCastContainer");
this.delegateEvents(this.events);
return this;
},
initialize: function () {
_.bindAll(this, 'render');
this.template = $("#newBroadcastDialogTemplate").html();
this.render();
}
});
You might want to try this. I had to refactor your code a bit hope you will get the idea
Slx.Dialogs.NewBroadcastDialog.View = Backbone.View.extend({
el:"#newBroadCastContainer",
template:$("#newBroadcastDialogTemplate").html(),
events: {
"click .dialog-content": "clickTest"
},
clickTest : function () {
alert("click");
},
render: function () {
var compiledTemplate = Handlebars.compile(this.template);
var renderedContent = compiledTemplate();
$(this.el).html(renderedContent).hide().dialog(this.options.dialogConfig);
return this;
},
initialize: function () {
}
});
Instantiate and render outside the View definition
var myDialog = new Slx.Dialogs.NewBroadcastDialog.View({dialogConfig:{title: Slx.User.Language.dialog_title_new_message,width: 500}});
myDialog.render();
The problem turned out to be due to me assigning this.el when I should have been assigning this.$el
This worked perfectly:
Slx.Dialogs.NewBroadcastDialog.View = Backbone.View.extend({
el: "#newBroadcastContainer",
events: {
"click .clicktest": "clickTest"
},
clickTest : function () {
console.log("click");
},
render: function () {
var compiledTemplate = Handlebars.compile(this.template);
var renderedContent = compiledTemplate();
var options = {
title: Slx.User.Language.dialog_title_new_message,
width: 500
};
this.$el = $(renderedContent).dialog(options);
return this;
},
initialize: function () {
_.bindAll(this, 'render');
this.template = $("#newBroadcastDialogTemplate").html();
this.render();
}
});
I had two codebases on one of the code base I was able to bind events by assigning the dialog to this.$el however in the other codebase this somehow did not work. I add the following line this.el = this.$el;
to the code and it is working now. however I am still not able to figure out why it was working in one codebase and not the other and why assigning $el to el got it to work.

access function in one view from another in backbone.js

I have this structure of views:
window.templateLoaderView = Backbone.View.extend({});
window.PopupView = templateLoaderView.extend({
initialize: function () {
this.PopupModel = new PopupModel();
this.event_aggregator.bind("tasks_popup:show", this.loadTaskPopup);
},
render: function() {
template= _.template($('#'+this.PopupModel.templateName).html());
$(this.el).html(template(this.PopupModel.toJSON()));
$('#'+this.PopupModel.containerID).html(this.el);
},
loadTaskPopup: function() {
this.PopupModel.loadTemplate("popupTask_templateHolder", "/js/templates/popup_task.html", "1", "container_dialog");
this.render();
}
});
window.TaskbarView = templateLoaderView.extend({
initialize: function () {
this.TaskbarModel = new TaskbarModel();
this.PopupModel = new PopupModel();
},
loadTaskbarPopup: function() {
this.event_aggregator.trigger("tasks_popup:show");
}
});
So I would like to runf function in one view form another. As far as I understand, I need to bind them somehow. Is it possible to bind them in initialize function?
I saw here example: Backbone.js - Binding from one view to another? . They creating both objects and than somehow binding them.
Thanks in advance,
I am kind of a fan of using the "Event Aggregator" pattern. I make sure that every view is given a copy of the same event aggregator object and they can all talk to each other through it... kind of like a CB radio :)
Do this before you create any views:
Backbone.View.prototype.event_aggregator = _.extend({}, Backbone.Events);
Now, you can publish/subscribe from anywhere:
window.PopupView = Backbone.View.extend({
initialize: function() {
_.bindAll(this, "loadTaskPopup");
this.model = new PopupModel();
this.event_aggregator.bind("tasks_popup:show", this.loadTaskPopup);
},
loadTaskPopup: function() {
// do something with this.model
}
});
window.TaskbarView = Backbone.View.extend({
loadTaskbarPopup: function() {
this.event_aggregator.trigger("tasks_popup:show")
}
});

Resources