I have a #root DOM object with many .element children:
<div id='root'>
<div class='element'>
<span>Element 1</span>
</div>
<div class='element'>
<span>Element 2</span>
</div>
<div class='element'>
<span>Element 3</span>
</div>
</div>
I want a Backbone View instance for every .element. This is what I have tried:
var ElementView = Backbone.View.extend({
initialize: function () {
_.bindAll(this, 'showText');
this.setElement('.element');
},
events: {
'click span': 'showText'
},
showText: function () {
console.log('You have clicked ' + $el.text());
}
});
I initialize my views as follows:
new ElementView({ model: modelInstance });
The problem is that .element is not precise enough, $el will be $('.element')[0] for every initialisation. How should I deal with the situation where many elements have the same CSS selector?
Initialize your views with their associated elements :
$(".element").each(function(ix,el) {
new ElementView({ model: modelInstance , el:el });
});
Dont' forget to remove this.setElement('.element'); in the initialize code.
Related
I have a Backbone Marionette ItemView which has two template which i want to open on a specific condition.
Backbone view is registering events for 1 template, but not firing for second template.
var emailView = Marionette.ItemView.extend({
initialize: function(){
},
getTemplate: function(){
if(this.options.position == 'a'){
//load tempalte 2
return template2;
} else {
//load template 1
return template;
}
},
events: {
//event from second template, not firing
'click #abcdef': 'a',
//event from first template, working
'click #sendemail': 'b'
},
a: function(){
alert("Hello");
},
b: function(){
alert("Hellob");
}
When i run template 1, event are working fine, but when i load template2, its not taking events for it.
Can guide me what i am doing wrong.
My 1st template:
<div id="emaildialog" title="" class="emaild">
<div class="row">
<div class="row1">
<button class="k-button" id="sendemail">Send</button>
</div>
</div>
</div>
My 2nd template:
<div id="emailconfiguredialog" class="emaild" title="">
<div class="row">
<div class="row1">
<button class="k-button" id="abcdef">Update Email</button>
</div>
</div>
</div>
I'm working with Backbone and for some reason I can't seem to show anything with the reset event. The stranger part is that when I trigger the add event it shows all my collection.
I'm using version 0.9.2 of Backbone:
Here's the code:
var TodoView = Backbone.View.extend({
tagName: 'li',
template: _.template($('#item-template').html()),
render: function(){
this.$el.html(this.template(this.model.toJSON()));
return this; // enable chained calls
}
});
var CoursesPageView = Backbone.View.extend({
el: '.page',
initialize: function () {
this.input = this.$('#new-todo');
todoList.on('add', this.addAll2, this);
todoList.on('reset', this.addAll, this);
console.log("getting ready to fetch localstorage");
todoList.fetch(); // Loads list from local storage
// Also triggers reset event
},
render: function(){
console.log("function: render2");
var template = _.template($("#courses").html(),{});
this.$el.html(template);
},
events: {
'keypress #new-todo': 'createTodoOnEnter'
},
createTodoOnEnter: function(e){
if ( e.which !== 13) { // ENTER_KEY = 13
return;
}
console.log("function: createOnEnter");
todoList.create({title: $('#new-todo').val()}); // triggers add event
console.log("passed to localstorage: " + $('#new-todo').val());
$('#new-todo').val(''); // cleans input box once enter is pressed
},
addOne: function(todo){
var view = new TodoView({model: todo});
console.log("show li");
$('#todo-list').append(view.render().el);
},
addAll: function(){
console.log("reset event triggered");
this.$('#todo-list').html(''); // clean the todo list
todoList.each(this.addOne, this);
},
addAll2: function(){
console.log("add event triggered");
this.$('#todo-list').html(''); // clean the todo list
todoList.each(this.addOne, this);
},
});
and for the index.html file part:
<script type="text/template" id="courses">
<div class="navbar navbar-inverse navbar-fixed-top">
<div class="navbar-inner">
<div class="container">
<h4 align="center" style="color:white;">Courses</h4>
</div>
</div>
</div>
<div class="container">
Add Course
<input id="new-todo">
<section id="main">
<ul id="todo-list"></ul>
</section>
</div>
</script>
<script type="text/template" id="item-template">
<div class="view">
<label><%- title %></label>
</div>
</script>
I have html markup ready, which is not going to change, I want to just add/update variables in this markup.
How do I do this using backbone and underscore?
I have tried the following,
Backbone:
testView = Backbone.View.extend({
initialize: function(){
this.render();
},
render: function(){
var variables = {reqNumber: 10};
/*This is where I'm having problems, how do I use only variables in my template??
* How do I write this next line
*/
var template = _.template(this.$el.html(), variables);
this.$el.html(template);
}
});
var test_view = new testView({ el: $("div.container") });
HTML:
<a href="#">
<i class="icon-home icon-white"></i>
Requests <span class="badge badge-warning"><%= reqNumber %></span>
</a>
Something like this works. The problem was, you didn't identify where your template was as this.$el points to the view's container, not the template (see the template script).
JS:
$(function() {
var testView = Backbone.View.extend({
initialize: function(){
this.render();
},
render: function(){
var variables = {'reqNumber': '10'};
var template = _.template($('#test-templ').html(), variables);
this.$el.html(template);
}
var test_view = new testView({ el: $("div.container") });});
});
HTML:
<script id="test-templ" type="text/html">
<a href="#">
<i class="icon-home icon-white"></i>
Requests <span class="badge badge-warning"><%= reqNumber %></span>
</a>
</script>
<div class="container"></div>
I can't get this thing to add when i click the add button. I'm completely new to this.
JS code
function RecipeApp() {
var _Ingredient=Backbone.Model.extend(COOKBOOK.Domain.Ingredient),
_Ingredients = Backbone.Collection.extend({
model: _Ingredient
}),
_IngredientView = Backbone.View.extend({
tagName: "li",
initialize: function () {
this.model.bind("change", this.render, this);
},
render: function () {
var templateid = this.model.get('ViewID');
$(this.el).html(Mustache.to_html($("#"+templateid).html(),this));
}
}),
_AddView = Backbone.View.extend({
id:"divAddIngredient",
events: {
"click .btn": "create"
},
render: function () {
var tmpAddAnIngredient = $("#tmpMasterView").html(),
$submain = $("#submain");
$submain.html(Mustache.to_html(tmpAddAnIngredient, COOKBOOK.Domain));
},
initialize: function (ingredients) {
console.log("init enter");
this.render();
this._Ingredients = ingredients;
this._Ingredients.bind('add', this.add, this);
console.log("init leave");
},
//added functions
create: function () {
console.log("create");
var typename = this.$(".typeName").val(),
ingredient = _.detect(COOKBOOK.Domain.Ingredients, function (i) { i.TypeName === typename });
if (!!ingredient) {
this._Ingredients.create(ingredient);
}
},
add: function (ingredient) {
console.log('add');
var view = new _IngredientView(ingredient);
this.$("#divIngredients").append(view.render().el);
}
});
this.Ingredients = new _Ingredients();
this.AddView = new _AddView(this.Ingredients);
}
$(function () {
window.app = new RecipeApp();
//
});
And here is the mustache template
<script id="tmpTempDirectoryIngredient" type="text/html">
<div class="block-message">
<form>
<fieldset>
<legend>Create a Temporary Directory</legend>
<div class="clearfix">
<input type="text" name="DirectoryName" class="DirectoryName" />
</div>
</fieldset>
</form>
</div>
</script>
<script id="tmpMasterView" type="text/html">
<div class="block-message info" id="divAddIngredient">
<form>
<fieldset>
<legend>Add an Ingredient</legend>
<div class="clearfix">
<select class="typeName">
{{#Ingredients}}
<option value="{{TypeName}}">{{Name}}</option>
{{/Ingredients}}
</select>
</div>
<div class="clearfix">
<input type="button" class="btn primary" value="Add Ingredient" />
</div>
</fieldset>
</form>
</div>
<hr />
<div id="divIngredients">
</div>
</script>
it started working as soon as i explicitly set the el property of the _AddView to a tag that existed when the _AddView was created.
$(function(){
new Apps({el:$("body"),'records':[1,2,3,4,5]});
});
Here need to give el.
because of only after DOM is generating.....
The way you are passing Ingredients to the _AddView initialize, they will be accessible by this.options (see http://documentcloud.github.com/backbone/#View-constructor).
I think a better way is pass your ingredients collection into you _AddView like this:
this.AddView = new _AddView({collection: this.Ingredients});
Then within your definition of your view, always refer to this.collection instead of this._Ingredients. That is I think a more standard way to do it.
my backbone view looks like this below and is rendered with the jQuery tmpl library. I want to apply a style to one/all/any of the data items for which
active==1. Any ideas on how to do this?
// backbone view
window.CaseView = Backbone.View.extend({
el: $("#main"),
initialize: function() {
_.bindAll(this, 'render');
this.render();
},
iTemplate: $("#tmplCase").template(),
render: function() {
var that = this;
that.el.fadeOut('fast', function() {
$.tmpl(that.iTemplate, that.model.toJSON()).appendTo(that.el);
that.el.fadeIn('fast');
});
return this;
}
});
// html file
<div id="main"></div>
<script id="tmplCase" type="text/x-jquery-tmpl">
<div class="caseInActive">
<span class="title">${title}</span>
<span class="current_status">${active}</span>
</div>
</script>
you can add if statements to your template:
// html file
<script id="tmplCase" type="text/x-jquery-tmpl">
<div {{if active == 1}}class="caseInActive"{{/if}}>
<span class="title">${title}</span>
<span class="current_status">${active}</span>
</div>
</script>
http://api.jquery.com/template-tag-if/