Having a simple template with backbone.js -
jsTemplateBackbone.html
<html>
<head>
<script src="jquery-2.1.0.min.js"></script>
<script src="json2.min.js"></script>
<script src="underscore.js"></script>
<script src="backbone.js"></script>
<!--Order is important !!!-->
</head>
<body>
<script type="text/template" id="item-container">
<li><%= value %></li>
</script>
<script src="jsBackboneHomeView.js"></script>
</body>
</html>
jsBackboneHomeView.js
//Model
Wine = Backbone.Model.extend();
// Collection
Wines = Backbone.Collection.extend({
Model: Wine,
url: "#"
});
// Collection object
wines = new Wines([
{ name: "Robert Mondovi" },
{ name: "CakeBread" }
]);
// List
ListView = Backbone.View.extend({
tagName: 'ul',
initialize: function () {
// grabing the html template
this.template = _.template($('#item-container').html());
},
render: function () {
var el = this.$el, template = this.template;
el.empty();
wines.each(function (wine) {
el.append(template(wine.toJSON()));
});
return this;
}
});
// View
HomeView = Backbone.View.extend({
el: 'body',
initialize: function () {
this.render();
},
render: function () {
this.$el.empty();
this.$el.append("<h1>My App</h1>");
listView = new ListView();
// append two <li> on <ul> and return it
this.$el.append(this.listView.render().el);
return this;
}
});
// View instance
wineApp = new HomeView();
when I execute it , it gives an error -
Uncaught TypeError: Cannot call method 'replace' of undefined - underscore.js:1236
line 1236 - text.replace(matcher, function(match, escape, interpolate, evaluate, offset) {
What is wrong here ?
(The code taken from this tutorial . )
The property in your model is called name while it is value in your template, and thus it can't be replaced. Try :
<li><%= name %></li>
in your template.
in your ListView render function, instead of returning this, return the values you want to be available as an object,
e.g.
return({
el: el
});
Related
I am struggling with displaying two models/collections in the same page.
<body>
<div id="mainContainer">
<div id="contentContainer"></div>
</div>
<div id="mainContainer2">
<div id="contentContainer2"></div>
</div>
<script id="list_container_tpl" type="text/template">
<div class="grid_5 listContainer">
<div class="box">
<h2 class="box_head grad_colour">Your tasks</h2>
<div class="sorting">Show: <select id="taskSorting"><option value="0">All Current</option><option value="1">Completed</option></select>
<input class="search round_all" id="searchTask" type="text" value="">
</div>
<div class="block">
<ul id="taskList" class="list"></ul>
</div>
</div>
</div>
</script>
<script id="list2_container_tpl" type="text/template">
<div class="grid_5 mylistContainer">
<div class="box">
<h2 class="box_head grad_colour">Your facets</h2>
<div class="sorting">
%{--Show: <select id="taskSorting"><option value="0">All Current</option><option value="1">Completed</option></select>--}%
<input class="search round_all" id="searchFacet" type="text" value="">
</div>
<div class="block">
<ul id="facetList" class="list"></ul>
</div>
</div>
</div>
</script>
<script id="task_item_tpl" type="text/template">
<li class="task">
<h4 class="name searchItem">{{ name }}</h4>
</li>
</script>
<script id="facet_item_tpl" type="text/template">
<li class="facet">
<h5 class="label searchItem">{{ label }}</h5>
</li>
</script>
<script>
var myapp = {
model: {},
view: {},
collection: {},
router: {}
};
var facetsSearch = {
model: {},
view: {},
collection: {},
router: {}
};
</script>
<script src="underscore-min.js"></script>
<script src="handlebars.min.js"></script>
<script src="backbone-min.js"></script>
<script>
/* avoid */
_.templateSettings = {
interpolate: /\{\{(.+?)\}\}/g
};
</script>
<script>
// model.tasks.js
myapp.model.Tasks = Backbone.Model.extend({
default:{
completed: 0,
name: ""
},
//url:"/js/libs/fixtures/task.json"
});
var tasks1 = new myapp.model.Tasks({
completed: 0,
name: "Clear dishes"
}
);
var tasks2 = new myapp.model.Tasks({
completed: 1,
name: "Get out the trash"
}
);
var tasks3 = new myapp.model.Tasks({
completed: 0,
name: "Do the laundry"
}
);
var tasks4 = new myapp.model.Tasks({
completed: 1,
name: "Vacuuming the carpet"
}
);
// collection.tasks.js
myapp.collection.Tasks = Backbone.Collection.extend({
currentStatus : function(status){
return _(this.filter(function(data) {
return data.get("completed") == status;
}));
},
search : function(letters){
if (letters == "") return this;
var pattern = new RegExp(letters,"gi");
return _(this.filter(function(data) {
return pattern.test(data.get("name"));
}));
}
});
myapp.collection.tasks = new myapp.collection.Tasks([tasks1, tasks2, tasks3, tasks4]);
// route.tasks.js
myapp.router.Tasks = Backbone.Router.extend({
routes: {
"": "list",
},
list: function(){
this.listContainerView = new myapp.view.TasksContainer({
collection: myapp.collection.tasks
});
$("#contentContainer").append(this.listContainerView.render().el);
this.listContainerView.sorts()
}
});
myapp.router.tasks = new myapp.router.Tasks;
<!-- render views -->
myapp.view.TasksContainer = Backbone.View.extend({
events: {
"keyup #searchTask" : "search",
"change #taskSorting" : "sorts"
},
render: function(data) {
$(this.el).html(this.template);
return this;
},
renderList : function(tasks){
$("#taskList").html("");
tasks.each(function(task){
var view = new myapp.view.TasksItem({
model: task,
collection: this.collection
});
$("#taskList").append(view.render().el);
});
return this;
},
initialize : function(){
this.template = _.template($("#list_container_tpl").html());
this.collection.bind("reset", this.render, this);
},
search: function(e){
var letters = $("#searchTask").val();
this.renderList(this.collection.search(letters));
},
sorts: function(e){
var status = $("#taskSorting").find("option:selected").val();
if (status == "") status = 0;
this.renderList(this.collection.currentStatus(status));
}
});
myapp.view.TasksItem = Backbone.View.extend({
events: {},
render: function(data) {
$(this.el).html(this.template(this.model.toJSON()));
console.log(this.model.toJSON(), "became", this.template(this.model.toJSON()));
return this;
},
initialize : function(){
this.template = _.template($("#task_item_tpl").html());
}
});
</script>
<script>
// model.facets.js
facetsSearch.model.Facets = Backbone.Model.extend({
default: {
id: 0,
label: "",
facetValues: []
}
});
var facet1 = new facetsSearch.model.Facets({
id: 1,
label: "Organism",
facetValues: ["Orga1", "Orga2"]
});
var facet2 = new facetsSearch.model.Facets({
id: 2,
label: "Omics",
facetValues: ["Omics1", "Omics2"]
});
var facet3 = new facetsSearch.model.Facets({
id: 3,
label: "Publication Date",
facetValues: ["2016-11-01", "2016-11-02"]
});
// collection.facets.js
facetsSearch.collection.Facets = Backbone.Collection.extend({
search : function(letters){
if (letters == "") return this;
/**
* the g modifier is used to perform a global match (find all matches rather than stopping after the first match).
* Tip: To perform a global, case-insensitive search, use this modifier together with the "i" modifier.
*/
var pattern = new RegExp(letters, "gi");
return _(this.filter(function(data) {
return pattern.test(data.get("label"));
}));
}
});
facetsSearch.collection.facets = new facetsSearch.collection.Facets([facet1, facet2, facet3]);
// route.facets.js
facetsSearch.router.Facets = Backbone.Router.extend({
routes: {
"": "list",
},
list: function(){
this.mylistContainerView = new facetsSearch.view.FacetsContainer({
collection: facetsSearch.collection.facets
});
console.log("Facet collection: ", facetsSearch.collection.facets);
$("#contentContainer2").append(this.mylistContainerView.render().el);
this.mylistContainerView.sorts()
}
});
facetsSearch.router.Facets = new facetsSearch.router.Facets;
facetsSearch.view.FacetsContainer = Backbone.View.extend({
events: {
"keyup #searchFacet" : "search",
"change #facetSorting": "sorts"
},
render: function(data) {
$(this.el).html(this.template);
return this;
},
renderList : function(facets){
$("#facetList").html("");
facets.each(function(facet){
var view2 = new facetsSearch.view.FacetsItem({
model: facet,
collection: this.collection
});
$("#facetList").append(view2.render().el);
});
return this;
},
initialize : function(){
this.template = _.template($("#list2_container_tpl").html());
this.collection.bind("reset", this.render, this);
},
search: function(e){
var letters = $("#searchFacet").val();
this.renderList(this.collection.search(letters));
},
sorts: function(e){
/*var status = $("#taskSorting").find("option:selected").val();
if (status == "") status = 0;
this.renderList(this.collection.currentStatus(status));*/
}
});
facetsSearch.view.FacetsItem = Backbone.View.extend({
events: {},
render: function(data) {
$(this.el).html(this.template(this.model.toJSON()));
console.log(this.model.toJSON(), "became", this.template(this.model.toJSON()));
return this;
},
initialize : function(){
this.template = _.template($("#facet_item_tpl").html());
}
});
</script>
<script>
Backbone.history.start();
</script>
</body>
The problem
To display Tasks above Your facets. I created two bunches of codes to render Tasks and Facets but modified the variable names respectively. Unfortunately, the former cannot be displayed.
As Emile mentioned in his detailed answer, your problem is that you're initializing multiple routers with the same route.
Since you seem to be beginning with Backbone, I'll give you a simpler answer than creating a complicated Layout (parent) view:
Just have a single handler for the specific route, and initialize both your views inside it.
It'll look something like:
myapp.router = Backbone.Router.extend({
routes: {
"": "list",
},
list: function() {
this.listContainerView = new myapp.view.TasksContainer({
collection: myapp.collection.tasks
});
$("#contentContainer").append(this.listContainerView.render().el);
this.listContainerView.sorts(); //this can be done inside the view
this.mylistContainerView = new facetsSearch.view.FacetsContainer({
collection: facetsSearch.collection.facets
});
$("#contentContainer2").append(this.mylistContainerView.render().el);
this.mylistContainerView.sorts(); //this can be done inside the view
}
});
You simply initialize 2 views in the same route.
You made 2 routers, both with an empty route. Each route is registered in Backbone.history, so when the facets router is initialized, its route overrides the tasks router route.
How to have multiple routers?
For the scope of your application, you should just start by making a single router, and handling the page with 2 lists within a parent view. Make a sort of Layout view for that page, which will handle the 2 lists:
var Layout = Backbone.View.extend({
template: _.template($('#layout-template').html()),
// keep the selector strings in a simple object
selectors: {
tasks: '.task-container',
facets: '.facet-container',
},
initialize: function() {
this.view = {
tasks: new TaskList(),
facets: new FacetList()
};
},
render: function() {
this.$el.html(this.template());
var views = this.views,
selectors = this.selectors;
this.$(selectors.tasks).append(views.tasks.render().el);
this.$(selectors.facets).append(views.facets.render().el);
return this;
}
});
Then, only one router:
var Router = Backbone.Router.extend({
routes: {
"": "list",
},
list: function() {
this.listContainerView = new Layout();
$("body").html(this.listContainerView.render().el);
}
});
This won't work with your code as-is, you'll have to incorporate the concepts yourself into your app.
Otherwise, if you really want multiple routers, you must understand that they can't share a route and that at any moment, only one route can be triggered.
When you have multiple routers, each manages the routes of a single module.
var TaskRouter = Backbone.Router.extend({
routes: {
'tasks': 'taskList',
'tasks/:id': 'taskDetails'
}
// ...snip...
});
var FacetsRouter = Backbone.Router.extend({
routes: {
'facets': 'facetList',
'facets/:id': 'facetDetails'
}
// ...snip...
});
Other improvements
Compile the template once
It's more efficient to compile the template once, when the view is being extended, than each time a new view is initialized.
myapp.view.TasksContainer = Backbone.View.extend({
// gets compiled once
template: _.template($("#list_container_tpl").html()),
initialize: function() {
// not here, as it gets compiled for each view
// this.template = _.template($("#list_container_tpl").html())
},
});
Avoid the global jQuery function
Avoid $(this.el) in favor of this.$el.
Avoid $('#divInTemplate') in favor of this.$('.divInTemplate'). It's a shortcut to this.$el.find.
See What is the difference between $el and el for additional informations.
Cache the jQuery objects
Whenever you want to select a child of the view's element, do it once and put the result in a variable.
render: function(data) {
this.$el.html(this.template);
// I like to namespace them inside an object.
this.elements = {
$list: this.$('.task-list'),
$search: this.$('.task-sorting')
};
// then werever you want to use them
this.elements.$list.toggleClass('active');
return this;
},
Use listenTo
Avoid bind/unbind and on/off/once (aliases) in favor of listenTo/stopListening/listenToOnce.
listenTo is an improved version of bind which solves problem with memory leaks.
this.collection.bind("reset", this.render, this);
// becomes
this.listenTo(this.collection, "reset", this.render);
Pass an array of objects to collection
myapp.collection.Tasks = Backbone.Collection.extend({
model: myapp.model.Tasks
// ...snip...
});
myapp.collection.tasks = new myapp.collection.Tasks([{
completed: 0,
name: "Clear dishes"
}, {
completed: 1,
name: "Get out the trash"
}, {
completed: 0,
name: "Do the laundry"
}, {
completed: 1,
name: "Vacuuming the carpet"
}]);
This would be enough, Backbone collection takes care of the rest.
I am wondering how to log the model used in a Backbone.Marionette CompositeView's template?
The <% console.log(model) %> I am using causes an error Uncaught ReferenceError: model is not defined
Is there a way to log the content of the model from the template?
Here is a fiddle to my code: http://jsfiddle.net/16L1hen4/
Here is my Template and JavaScript
Template:
<div id="main"></div>
<script type="text/template" id="tree-template">
<li><%- name %></li>
<% //This console.log fails and I don't know why %>
<% console.log('inside template model =',model) %>
</script>
JavaScript:
var App = new Backbone.Marionette.Application();
App.addRegions({
mainRegion: '#main'
});
var TreeModel = Backbone.Model.extend({
});
var TreeCollection = Backbone.Collection.extend({
model: TreeModel,
url: 'https://api.mongolab.com/api/1/databases/backbone-tree/collections/tree?apiKey=akey'
});
// Tree branch view
var CompositeView = Backbone.Marionette.CompositeView.extend({
tagName: 'ul',
template: _.template( $('#tree-template').html() )
});
// Tree root view
var CollectionView = Backbone.Marionette.CollectionView.extend({
tagName: 'div',
className: 'js-tree-root',
childView: CompositeView,
});
var treeCollection = new TreeCollection();
treeCollection.fetch().done(function () {
var collectionView = new CollectionView({collection: treeCollection});
App.mainRegion.show(collectionView);
});
Edit: In a regular Backbone.View I can pass the model to the data as a property. Notice in this example that the View's model is passed to the template with a data property which can be logged in the template. This could be useful in the template to test for the existance of properties on the model. I am not sure how to do this using a Marionette CompositeView
var jsonData = {
"color": "red"
};
var TheModel = Backbone.Model.extend({
});
var TheView = Backbone.View.extend({
el: '#main',
tagName: 'ul',
template: _.template( $('#the-template').html() ),
render: function () {
var tmpl = this.template({data: this.model.toJSON()});
this.$el.html( tmpl );
}
});
var theModel = new TheModel(jsonData);
var theView = new TheView({model: theModel});
theView.render();
<div id="main"></div>
<script type="text/template" id="the-template">
<li><%- data.color %></li>
<% //Log the current model that the template uses %>
<% console.log('template model =',data) %>
</script>
This happens to be related to the anwser I posted on your question here : Backbone Marionette Composite View Rendering Template
and is cause by the same issue. model being undefined in the template context.
The data passed to your template is the following:
{_id: Object, name: "Level 1", children: Array[2]}
and model is undefined in this context.
If you want to log/control the data passed to your template you have should use SerializeData in such a way:
var CompositeView = Backbone.Marionette.CompositeView.extend({
tagName: 'ul',
serializeData: function(){
var data = Backbone.Marionette.CompositeView.prototype.serializeData.apply(this, arguments);
console.log(data);
return data;
},
template: _.template( $('#tree-template').html() )
});
I have the following a very simple ToDo List app using Backbone framework.
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>To do List</title>
<style>
.completed{
text-decoration: line-through;
color: #666;
}
</style>
<script type="text/javascript" src="http://code.jquery.com/jquery-1.11.1.js"></script>
<script type="text/javascript" src="js/underscore.js"></script>
<script type="text/javascript" src="js/backbone.js"></script>
</head>
<body>
<h1>My Todos</h1>
<div id="tasks">
<button class="add">Add Task</button>
<button class="clear hide">Clear All</button>
<ul></ul>
</div>
<script id="taskTemplate" type="text/template">
<span class="<%= completed ? 'completed' : 'incomplete' %>"><%= text %></span>
<button class="complete"></button>
<button class="delete"></button>
</script>
<script type="text/javascript">
var Task = Backbone.Model.extend({
defaults: {text: 'New task', completed: false}
});
var Tasks = Backbone.Collection.extend({
model: Task,
el: '#tasks',
initialize: function(){
this.collection = new Tasks;
this.collection.on('add', this.appendNewTask, this);
this.items = this.$el.children('ul');
},
add: function(){
var text = prompt('What do you need to do?');
var task = new Task({text: text});
this.collection.add(task);
},
appendNewTask: function(task){
var TasksView = new TasksView({model:task});
this.items.append(TasksView.el);
},
completed: function(){
return _.filter(this.models, function(model){
return model.get('completed');
});
}
});
var TasksView = Backbone.View.extend({
tagName: 'li',
el: '#tasks',
template: _.template($('#taskTemplate').html()),
initialize: function(){
this.model.on('change', this.render, this);
this.model.on('remove', this.unrender, this);
this.render();
},
render: function(){
var markup = this.template(this.model.toJSON());
this.$el.html(markup);
},
unrender: function(){
this.$el.remove();
},
events: {
'click .add': 'add',
'click .clear': 'clearCompleted',
'click .delete': 'delete',
'click .complete': 'updateStatus',
'dblclick span': 'edit'
},
add: function(){
var text = prompt('What do you need to do?');
var task = new Task({text: text});
},
delete: function(){
this.model.destroy();
this.$el.remove();
},
updateStatus: function(){
this.model.set('completed', !this.model.get('completed'));
},
edit: function(){
var text = prompt('What should we change your task to?', this.model.get('text'))
this.model.set('text',text);
},
clearCompleted: function(){
var completedTasks = this.collection.completed();
this.collection.remove(completedTasks);
}
});
new TasksView;
</script>
<!-- Template JS -->
</body>
</html>
When I visit and load the page, and I could see an uncaught javascript error in the console log.
Uncaught TypeError: Cannot read property 'on' of undefined on line 78.
Looking through the code at the indictaed line number, it pointed to this
var TasksView = Backbone.View.extend({
//.....
initialize: function(){
this.model.on('change', this.render, this); // this is the line the console is complaining
this.model.on('remove', this.unrender, this);
this.render();
},
//.....
});
After staring this for the next couple of hours and analysed the code, I couldn't figure out why this model needs to be instantiated when no tasks have been added to the TaskView Objects yet. It should be initialized as soon as I add or remove a new Task item into the model. I don't quite understand how this would throw an exception.
BTW, I'm a very new to Backbone.js and Underscore.js. I'm just following an online tutorial to figure out how these frameworks work...
Thanks.
You are not binding any model to your view. You can pass a model and/or collection when instantiating your new view. These properties will automatically be bound to this.model / this.collection of your view.
You are not passing a model so this.model is undefined in your view. You should pass the empty taskslist so that when it's populated later, the onchange will be triggered and your view will rerender.
new TasksView({model: new Tasks()});
I asked question the other day on this app; after some good advice, I moved on and I now think this is a different issue.
Before, I was not getting any display on the screen/no errors or any console.logs. After working on it some more, I now have my model/view and some of my render function working.
I think the issue is with my template or with my append. Below is the full code as it stands now. There are //comments where I think there maybe some issues.
Any help with this would be greatly appreciated.
EDIT :: Thanks for the advice Niranjan. I made some the changes you mentioned; I took away the counter and sample data. With these new changes, my newsFeed.js is no longer being read and so I am unclear as to how to populate my collection. When I console.log out my collection I get an empty array with my defaults shown, but with the json file not being read in the first place how do I get anything to work?
EDIT#2 :: Thank you again Niranjan. With the changes you suggested and a few of my own, I now have the code below. The issue I have right now, Is my array is being populated far too many times. the JSON file has 8 entries in total and because of my _.each statement in my template it is looping 8 times where I only want it to loop once and then to split the array into separate entries. I tried first splitting it during my response parse but this didn't work, do you have any advice for this?
below the code is links to the live views of code and html/broswer content including a link to the JSON file.
My end goal is to click on one title and have the corresponding content show.
(function(){
var NewsFeedModel = Backbone.Model.extend({
defaults: {
title: '',
content: ''
}
});
var NewsFeedCollection = Backbone.Collection.extend({
model: NewsFeedModel,
url : 'newsFeed.js',
parse: function(response) {
console.log('collection and file loaded');
return response.responseData.feed.entries;
}
});
var NewsFeedView = Backbone.View.extend({
el : '.newsContainer ul',
template: _.template($("#feedTemp").html()),
initialize: function(){
var scopeThis = this;
_.bindAll(this, 'render');
this.collection.fetch({
success: function(collection){
scopeThis.render();
}
});
this.collection.bind( 'add', this.render, this);
console.log('View and Template read');
},
render: function () {
this.$el.html(this.template({
feed: this.collection.toJSON()
}));
console.log(this.collection.toJSON());
}
});
var newsFeedCollection = new NewsFeedCollection();
var newsFeedView = new NewsFeedView({
collection: newsFeedCollection
});
var title = newsFeedCollection.find('title');
var content = newsFeedCollection.find('content > title');
$(document).on("click", "#add", function(title, content) {
console.log("I have been clicked");
if($(title) == $(content)){
console.log('they match');
}
else{
console.log('they dont match');
}
$('.hide').slideToggle("slow");
});
}());
This is my underscore template.
<div class="span12">
<script id="feedTemp" type="text/template">
<% _.each(feed, function(data) { %>
<div id = "titleContent">
<%= data.title %>
<div id="content" class="hide">
<%= data.content %>
</div>
</div>
<% }); %>
</script>
</div>
I am using google drive as a testing ground; links for the full html/code.
https://docs.google.com/file/d/0B0mP2FImEQ6qa3hFTG1YUXpQQm8/edit [code View]
https://googledrive.com/host/0B0mP2FImEQ6qUnFrU3lGcEplb2s/feed.html [browser View]
https://docs.google.com/file/d/0B0mP2FImEQ6qbnBtYnVTWnpheGM/edit [JSON file]
There are lot more things in your code that can be improved.
Here is the JSFIDDLE.
Please go through the comments mentioned in the code.
For trying out things in Underscore's template, check Underscore's Template Editor.
Template:
<button id=add>Add</button>
<div class="newsConatiner">
<ul></ul>
</div>
<script id="feedTemp">
<% _.each(feed, function(data) { %>
<div id = "titleContent">
<h2> <%= data.title %> </h2>
<div id="content">
<%= data.content %>
</div>
</div>
<% }); %>
</script>
Code:
(function () {
var NewsFeedModel = Backbone.Model.extend({
//url: 'newsFeed.js',
defaults: {
title: '',
content: ''
}
});
var NewsFeedCollection = Backbone.Collection.extend({
model: NewsFeedModel,
url: 'newsFeed.js',
parse: function (response) {
console.log('collection and file loaded');
return response.responseData.feed.entries;
}
});
var NewsFeedView = Backbone.View.extend({
el: '.newsConatiner',
//template should not be inside initialize
template: _.template($("#feedTemp").html()),
initialize: function () {
_.bindAll(this, 'render');
this.render();
//ADD event on collection
this.collection.bind('add', this.render, this);
console.log('View and Template read');
},
/*
This initialize will fetch collection data from newsFeed.js.
initialize: function () {
var self = this;
_.bindAll(this, 'render');
this.collection.fetch({
success: function(collection){
self.render();
}
});
//ADD event on collection
this.collection.bind('add', this.render, this);
console.log('View and Template read');
},
*/
render: function () {
//This is how you can render
//Checkout how this.collection is used
this.$el.html(this.template({
feed: this.collection.toJSON()
}));
}
});
//Initialized collection with sample data
var newsCounter = 0;
var newsFeedCollection = new NewsFeedCollection([{
title: 'News '+newsCounter++,
content: 'Content'
}]);
//Created view instance and passed collection
//which is then used in render as this.collection
var newsFeedView = new NewsFeedView({
collection: newsFeedCollection
});
$('#add').click(function(){
newsFeedCollection.add(new NewsFeedModel({
title: 'News ' + newsCounter++,
content: 'Content'
}));
});
}());
I find that when using templateHelpers and set it as a function, it is not displaying at all.
But when I use a variable inside the templateHelper, it is displaying. Basically what they have in this link https://github.com/marionettejs/backbone.marionette/blob/master/docs/marionette.view.md#viewevents, it is not working on my end.
The jsfiddle is in here http://jsfiddle.net/gerlstar/Ms7uN/2/
model2 = Backbone.Model.extend({
defaults: {
age: '',
name: ''
},
initialize: function () {
this.set({
name: "Terry"
});
}
});
someview = Marionette.ItemView.extend({
tagName: "div",
template: "#tpl-box",
templateHelpers: {
showMessage: function () {
return " is the coolest!";
}
}
});
var app = new Marionette.Application();
app.container = new Backbone.Marionette.Region({
el: "#container"
});
app.layout = new Backbone.Marionette.Layout.extend({
template: "#tpl-layout",
region: {
rgn: "#rgn1"
}
});
var m = new model2();
var view2 = new someview({
model: m
});
app.on("initialize:after", function() {
layout = new app.layout();
app.container.show(layout);
layout.rgn.show(view2);
});
app.start();
HTML
<div id="container" class="container"></div>
<script id="tpl-box" type="text/html">
<%= name %>
</script>
<script id="tpl-layout" type="text/html">
< h3 > My layout < /h3>
<div id="rgn1">
</div >
</script>
Here is your fixed fiddle http://jsfiddle.net/pSv9h/
You had two problem:
1. new keyword when defining your layout,
You shouldn't use the new keyword when extending a backbone/marionnete class.
app.layout = Backbone.Marionette.Layout.extend instead of app.layout = new Backbone.Marionette.Layout.extend
2. regions not region
You need to define your regions inside of regions not region