How to render a backbone collection into two views - backbone.js

I am using twitter bootstrap link. When the user clicks the link a bootstrap modal appears.
Now because of some bootstrap technical difficulties in modal rendering i need to seperate the link and put the modal out the navbar div.
So consider i have two separate div
<div id="linkDiv">
</div>
and
<div id="modalDiv">
</div>
Now i have only one View which makes a call to the server to get the collection
app.View.FriendRequestListView = Backbone.View.extend( {
templateModalLink: _.template($('#link').html()),
templateModal: _.template($('#modal').html()),
tagName: 'div',
initialize: function(){
this.friendRequestCollection = new app.Collection.FriendRequestCollection();
this.friendRequestCollection.bind("reset", this.render, this);
this.friendRequestCollection.fetch();
},
render: function() {
$(this.el).html(this.templateModalLink({
friendRequestCollection: this.friendRequestCollection}));
return $(this.el);
},
});
Than i can render only one div like following
var list = new app.View.FriendRequestListView();
$('#linkDiv').html(list.$el);
My question is , Is it possible to render two templates at the same time and add the two templates to different DIV like for example in my case i want to get update
templateModalLink template to linkDiv and templateModal template to modalDiv with the collection I am getting from the server.

You have to instantiate the collection before app.View.FriendRequestListView(s) and pass app.View.FriendRequestListView(s) the collection:
var friendRequests = new app.Collection.FriendRequestCollection();
friendRequests.fetch(
success: function(collection, response, options) {
var list1 = new app.View.FriendRequestListView({collection: collection});
var list2 = new app.View.FriendRequestListView({collection: collection});
$('#linkDiv').html(list1.$el);
$('#modalDiv').html(list2.$el);
}
);

Related

adding a class to Handlebar template during initialise

I want to add a class to one of the elements in a Handlebar template while initialising the view.
Here is the where I initialise the LayoutView
export default LayoutView.extend({
className: 'LandingPageHeaderDetail',
template: fs.readFileSync(`${__dirname}/LandingPageHeaderDetail.hbs`, 'utf8'),
initialize: function (options) {
this.setMenu(options)
},
setMenu (options) {
// in here I want to add a className to one of the elements
// in the template file
// for example template = <ul><li id="id1">dkjfls</li><li id="id2">kdjfkls</li>
// if (options == id1) { add class x to element} else { add class to y element }
}
My question is how do I navigate the template tree, find the element I'm looking for and add a class to it.
I've tried using jQuery selectors as follows: $('#id1') but it returns null, probably because the template hasn't rendered yet. Any ideas?
You can use Marionette's serializeData function.
initialize: function(options){
this.myOptions = options;
},
serializeData: function(){
return {id: this.myOptions};
}
Then you can create a helper for Handlebars using the answer from this question: Handlebars.js if block helper ==
Then in your template, put the actual logic to apply the class:
<ul>
<li id="id1" {{#if_eq id "id1"}}class="classname"{{/if_eq}}>dkjfls</li>
<li id="id2" {{#if_eq id "id2"}}class="classname"{{/if_eq}}>kdjfkls</li>
</ul>
As you said, you can't work with the template inside initialize function cause the template is not rendered yet. Use Render event, it's triggered after the view has been rendered.
Marionette.View.extend({
onRender: function(){
// manipulate the `el` here. it's already
// been rendered, and is full of the view's
// HTML, ready to go.
this.setMenu();
},
setMenu: function(){
// now i can manipulate the template...
}
});
Other solution would be to use serializeModel or templateContext.

Tabs in Backbone

I'm new with Backbone and I'm making an example app in which I have to include tabs. The thing is that I have a collection of cities and I want to create one tab for each city (the collection fetchs from the server). I made a view called TabsView, which in the render function passes the collection to a template, and this one loops through the collection and renders the tabs.
What I want to do is that the first tab appears as 'active'. What I've done for the moment is that each tab has a href to a route in the router which changes it's class to active using jquery. Don't know if this is the best way to do this but it works. Maybe there's a better way. Also, when the user clicks a tab, I want to be able to render other view.
Hope I made myself clear. Thanks, cheers,
Martin
Ok I solved this problem doing something like the following:
var Tabs = Backbone.View.extend({
template: JST['tabs'],
events: {
'click li' : 'switchTab'
},
tagName: 'ul',
className: 'nav-tabs',
render: function() {
this.renderTabs();
return this;
},
renderTabs: function() {
this.$el.html(this.template({ cities: this.cities }));
this.$('li:first').addClass('active');
},
switchTab: function(event) {
var selectedTab = event.currentTarget;
this.$('li.active').removeClass('active');
this.$(selectedTab).addClass('active');
}
});
It works fine, maybe it can be improved.

binding backbone events in jqMobi Nav, or when the dom elements are duplicated in the dom

I've been porting my app to use jqMobi and jqUI, but I've run into a problem with backbone delegating events.
The way jqUI creates a side nav bar is umm.... interesting to say the least.
Each panel can have a distinct nav bar, but the nav bar is never actually visible to the user, you populate the nav bar, and then jqUI copies the html into the div#menu element.
My view is fairly straightforward
MyApp.Views.UserMenu = Backbone.View.extend({
el: 'nav#user_menu',
initialize: function(){
//empty out and unbind in-case it is already populated
$(this.el).empty().unbind();
this.render();
},
events: {
"click div#add_friend": "new_friend"
},
render: function(){
$(this.el).append(HandlebarsTemplates['friends/new_friend']());
// here I am trying to change the 'el' to point to where the menu is in the DOM
this.el = 'div#menu';
this.delegateEvents();
return this;
},
new_friend: function(){
alert('clicked');
}
});
I've tried changing the el to the div#menu after populating the nav, but that isn't working. I've also tried populating the div#menu directly, but that doesn't seem to work either.
Any suggestions? I'm assuming the issue is that the elements are being moved, but it could be something else, and maybe I'm not sure how to debug the other case.

How can I create a Backbone View with two or more liked nodes?

Take a HTML tabbar as example. Usually you have a ul and a list of div's. All the Backbone examples that I have found, link the View with only one node by the 'el', 'tagName', etc...
HTML TabBar:
<div class=".tabbar">
<ul class=".tabbar-header">
<li>Cars</li>
<li>Houses</li>
</ul>
<div id="tab-cars" class=".tabbar-item">...</div>
<div id="tab-houses" class=".tabbar-item">...</div>
</div>
Backbone Code:
window.TabBarView = Backbone.View.extend({
el: ???,
tabs: [],
render:function (eventName) {
// Render all tabs in this.tabs
_.each(this.tabs, function (item, position) {
// Render each tab with item.render()
}, this);
return this;
}
});
window.TabBarItemView = Backbone.View.extend({
el: ???,
initialize:function () {
this.model.bind("change", this.render, this);
this.model.bind("destroy", this.close, this);
},
render:function (eventName) {
// Render the tab header and tab content
return this;
}
});
I wish to add several TabBarItemView's to the TabBarView and each one creates itself the li node inside the ul.tabbar-header and the div.tabbar-item as content.
I've written an article that addresses this issue: http://lostechies.com/derickbailey/2011/10/11/backbone-js-getting-the-model-for-a-clicked-element/
It will show you how you can either use a single view to do what you want, or a parent/child setup with a collection view and item view like you're showing in your sample code
you can go as far as to make a separate navigation view, and have the navigation add an item through the render method of your tab-item-view.
when you render the tab item view, you do something like navigation.add(new nav item);
and also add a way to remove the navigation item.
or you can keep the navigation in pure html and append a <li> item with jquery / javascript when you are rendering a tab below.
can't give you a fully working example though, if you really need it i can probably make one tonight,.

How to get Twitter Bootstrap Twipsy to work with Backbone.js

I can't get twitter bootstrap's modal to work with backbone.js.
The backbone view works fine.
window.CaseView = Backbone.View.extend({
tagName: "tr",
render: function() {
var that = this;
var tmpl = $("#tmplCase").render(that.model.toJSON());
$(that.el).html(tmpl);
return this;
},
events: {
"hover #pp-12444" : "open"
},
open: function() {
//console.dir(this);
$('#pp-12444').twipsy('show');
},
...
The twitter bootstrap js modules have been correctly loaded.
Try to initialize twipsy first and only then show it:
$('#pp-12444').twipsy({'placement': 'above'}).twipsy('show');
Did you make sure to include the necessary attributes on your #pp-1244 element? In the twipsy bootstrap demo, the text to display is set in the data-original-title attribute on the element.

Resources