Backbone & jQuery Tmpl - applying style to template item - backbone.js

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/

Related

backbone and underscore template rendering

I'm trying to use backbone to show on a page the result from an API call, I would like to iterate over the collection and create one entry for every element of the collection within my html. It seems I'm missing something cause I see the template tag rendered but none of my items are there. What's the problem with my code?
here the html
<div class="form-group" id="main">
<% _.each(collection, function(car) { %>
<div class="form-group">
<input class="form-control" /><%= car.get("model") %>
</div>
<% }); %>
</div>
and here js
var CarView = Backbone.View.extend({
el: "#main",
template: _.template($("#main").html()),
initialize: function() {
this.render();
},
render: function() {
$(this.el).html(this.template({collection: [{id:1, model:"ford"}, {id:2,model:"kia"}]}));
return this;
}
});
var carView = new CarView();
here the fiddle: https://jsfiddle.net/e5hg6rzp/3/
First of all I suggest you to keep your template in <script type='text'/template> ... </script> tag. Secondly you are using .get() method inside your template on plain objects which are do not have this method. In your example you can access property through a . -
<div class="form-group">
<input class="form-control" /><%= car.model %>
</div>
Check this fiddle
If you want to use Backbone.Collection when you should create Car Collection and Car Model:
var data = [{
id: 1,
model: "ford"
}, {
id: 2,
model: "kia"
}];
var CarView = Backbone.View.extend({
el: "#main",
template: _.template($("#templ").html()),
initialize: function() {
this.render();
},
render: function() {
return this.$el.html(this.template(new CarCollection(data)))
}
});
var CarModel = Backbone.Model.extend({
defaults: {
id: '',
model: ''
}
})
var CarCollection = Backbone.Collection.extend({
model: CarModel
})
var carView = new CarView();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/backbone.js/1.3.3/backbone.js"></script>
<div class="container">
<div class="form-inline panel panel-default">
<div class="form-group" id="main">
</div>
</div>
</div>
<script type='text/template' id='templ'>
<% _.each(models, function(car) { %>
<div class="form-group">
<input class="form-control" />
<%= car.get('model') %>
</div>
<% }); %>
</script>

how to replace view with another view in backbone.js on runtime

I am trying to build backbone.js application with twitter API.
the application that I am working on performs 3 tasks:1-returns the recent tweets on the user 's timeline, 2-returns the user profile 3- provides the ability to search in twitter. my problem is that I want the results of the search functionality to appear in the location of the tweets when the user clicks the search button. in my code there is view to display the tweets and another view to display the results of searching..how to put view in the place of another view on runtime. here is some of the code to explain the idea:
index.html :
<body>
<header role="banner">
<!—some code here-->
</header>
<div id="search" class="inner-search">
<form>
<label>Search for</label>
<input type="search" id="searchbox" style="width: 70%;"
autofocus="" placeholder="I'm looking for.."/>
<button id="searchbutton" style="width: 10%;">Go</button>
</form>
</div><!--search-view-->
<div class="inner-content">
<nav role="navigation">
<ul class="chapter-list">
………
</ul>
</nav>
<div role="main" class="main-content metrouicss">
<div id='timeline' class='timeline-view'>
<h3>Tweets </h3>
</div>
</div><!--main-->
<div role="right" class="right-content">
<h3>My Profile </h3>
<div id="profile" class="profile-view">
<!-- This would be the template -->
</div></div><!--right-->
</div> <!-- /.content-wrapper -->
<footer role="contentinfo">
<div class="inner-footer">
<p class="copyright">© Eva Hriekes, 2015. All rights
reserved.</p>
</div> <!-- /.inner-footer -->
</footer>
<!-- Template for profile -->
<script type="text/x-handlebars-template" id="profile-template">
<div class='tiles clearfix'>
<div class="tile double bg-color-orangeDark">
<div class="tile-content">
<img src="{{user.profile_image_url}}" class="place-left">
<h3 style="margin-bottom: 5px;">{{user.name}}</h3>
<p style="float:left;">{{user.description}}</p>
<div class="brand">
<div class="badge">{{user.followers_count}} Followers</div>
</div>
</div>
</div>
</div>
</script>
<!-- Template for timeline -->
<script type="text/x-handlebars-template" id="timeline-template">
<ul class='listview fluid'>
{{#each tweet}}
<li >
<div class='icon'>
<img src='{{user.profile_image_url}}'></img>
</div>
<div class='data'>
<h4>{{user.name}}</h4>
<p>{{format text}}</p>
<p class="timestamp" style="text-decoration:underline;">
<i>{{friendlyDate}}</i></p>
<p style="font-weight:bold;">Rating:
<i class="fa fa-star-o"></i><i class="fa fa-star-
o"></i><i class="fa fa-star-o"></i><i class="fa fa-star-
o"></i><i class="fa fa-star-o"></i></p>
</div>
</li>
{{/each}}
</ul>
</script>
<!-- Template for search results -->
<script type="text/x-handlebars-template" id="search-template">
<ul class='listview fluid'>
{{#each tweet}}
<li >
<div class='icon'>
<img src='{{user.profile_image_url}}'></img>
</div>
<div class='data'>
<h4>{{user.name}}</h4>
<p>{{format text}}</p>
<p class="timestamp" style="text-decoration:underline;">
<i>{{friendlyDate}}</i></p>
</div>
</li>
{{/each}}
</ul>
</script>
<script data-main="js/main" src="js/vendor/require.js"></script>
</body>
</html>
timeline view:
define(['jquery', 'handlebars', 'backbone', 'app/collection
/Timeline','app/view/ProfilePopupView'],
function($, Handlebars, Backbone, Timeline,ProfilePopupView) {
var com = com || {};
com.apress = com.apress || {};
com.apress.view = com.apress.view || {};
com.apress.view.TimelineView = Backbone.View.extend({
el: '#timeline',
template: Handlebars.compile($("#timeline-template").html()),
timeline: null,
events: {
'click .profile': 'showDialog'
},
initialize: function(options){
var self = this;
//create a collection for this view to render
self.timeline = new Timeline();//new
com.apress.collection.Timeline();
//initial render
self.render();
//force the fetch to fire a reset event
self.timeline.fetch({reset:true
});
self.listenTo(self.timeline, 'reset', self.render);
},
render: function(){
var self = this;
if(self.timeline.models.length > 0){
var output = self.template({tweet: self.timeline.toJSON()});
self.$el.append(output);
}
return self;
},
showDialog: function(options){
var self =this,
$target = $(options.currentTarget),
username = $target.data('user');
/**
* Reuse the profile view
**/
var profileView = new ProfilePopupView({user: username});
}
});
// export stuff:
return com.apress.view.TimelineView;
});
search view:
define(['jquery', 'backbone'], function($, Backbone) {
var com = com || {};
com.apress = com.apress || {};
com.apress.view = com.apress.view || {};
com.apress.view.SearchView = Backbone.View.extend({
el: '#search',
model: null,
events: {
'click #searchbutton': 'runSearch'
},
initialize: function(options){
var self = this;
self.model = options.model;
},
runSearch: function(e){
var self = this;
query = $('#searchbox').val();
e.preventDefault();
console.log('Run search against ' + query);
//force a reset
self.model.set('query', '', {silent: true});
self.model.set('query', query);
}
});
return com.apress.view.SearchView;
});
results view:
define(['jquery', 'backbone', 'handlebars','dialog'], function($,
Backbone, Handlebars,Dialog) {
var com = com || {};
com.apress = com.apress || {};
com.apress.view = com.apress.view || {};
com.apress.view.ResultsView = Backbone.View.extend({
el: '#results', /* or should be el="#timeline"???*/
model: null,
template: Handlebars.compile($("#search-template").html()),
initialize: function(options){
var self = this;
self.model = options.model;
self.model.fetch({
error: function(e){
self.model.trigger("app:error", {message: 'Error
retrieving timeline information'});
},
success: function(e){
self.model.trigger("app:success", {message: 'success
retrieving timeline information'});
}
});
self.listenTo(self.model,'change', self.render);
self.render();
},
render: function(){
console.log('Display now');
var self = this,
output = self.template({tweet: self.model.get('statuses')});
/* I want to delete this code and display the results
in the place of tweets*/
$.Dialog({
'title' : 'Search Results',
'content' : output,
'draggable' : true,
'overlay' : true,
'closeButton' : true,
'buttonsAlign': 'center',
'keepOpened' : true,
'position' : {
'zone' : 'left'
},
'buttons' : {
'OK' : {
'action': function(){}
}
}
});
}
});
return com.apress.view.ResultsView;
});
can anyone help me in doing what I want?

Backbone: reset event not showing anything in li

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>

How to render only values using backbone and underscore?

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>

Backbone.js Event Not firing

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.

Resources