Can't show a model info in template [closed] - backbone.js

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 6 years ago.
Improve this question
I would like to show my model in template, but I've a problem :
Uncaught ReferenceError: title is not defined
There's my code:
var NewsView2 = Backbone.View.extend({
NewsView: _.template(NewsView),
initialize: function () {
console.log(this);
this.$el.html(this.NewsView());
this.render();
},
render: function () {
this.$el.html(this.NewsView());
var html = this.NewsView(this.model.toJSON());
this.$el.append(html);
return this;
}
});
initialize:
var news2 = new News({
author: "costam",
});
var widok2 = new NewsView2({model: news2});
and code in my template:
<html>
<head>
</head>
<body>
<%= title %>
</body>
Someone could help me with that? I don't have any idea to do it.

Your model doesn't have title property. UnderScore template is complaining because it tries to look for title property in your News model that doesn't exist.
Your Backbone View :
var NewsView2 = Backbone.View.extend({
initialize: function () {
this.render();
},
render: function () {
var template = _.template($("#yourTemplate").html())
var html = template(this.model.toJSON());
this.$el.append(html);
return this;
}
});
Your Model :
var news2 = new News({ author: "costam", title : "Your title" });
Template :
<html>
<head>
</head>
<body>
<script type="text/template" id="yourTemplate">
<%= author %> // --> this should match/exist in your model
<%= title %> // --> this should match/exist in your model
</script>
</body>
Note : There are different ways to set backbone template like this.

Related

Backbone Marionettejs view does not change when model changed

I follow the example from this book https://leanpub.com/marionette-gentle-introduction. My problem is that the view does not rerender when i change the model by clicking on the button. As the answer from this question , i don't need to do anything because Backbone/MarionetteJS smart enough to change the view.
Here is the code
<!DOCTYPE html>
<html lang="en">
<head>
<title>Demo marionettejs</title>
<script src="./vendors/jquery/dist/jquery.js" type="text/javascript"></script>
<script src="./vendors/underscore/underscore.js" type="text/javascript"></script>
<script src="./vendors/backbone/backbone.js" type="text/javascript"></script>
<script src="./vendors/backbone.marionette/lib/backbone.marionette.js" type="text/javascript"></script>
</head>
<body>
<div id="main-region" class="container">
<p>Here is static content in the web page. You'll notice that it gets
replaced by our app as soon as we start it.</p>
</div>
<script type="text/template" id="contact-template">
<p><%- firstName %> <%- lastName %> : <%- time %> </p> <br />
<button>Change model</button>
</script>
<script type="text/javascript">
var ContactManager = new Marionette.Application();
ContactManager.Contact = Backbone.Model.extend({});
ContactManager.ContactView = Marionette.ItemView.extend({
template: "#contact-template",
initialize: function () {
this.currentMeterId = null;
},
events: {
"click button": "changeModel"
},
modelEvents: {
"change": "modelChanged"
},
changeModel: function() {
this.model.set("time", (new Date()).toString());
},
modelChanged: function() {
console.log("Model changed : " + this.model.get('time'));
},
//EDIT
onRender: function() {
//Create jsTree here.
}
});
ContactManager.on("before:start", function () {
var RegionContainer = Marionette.LayoutView.extend({
el: "#app-container",
regions: {
main: "#main-region"
}
});
ContactManager.regions = new RegionContainer();
});
ContactManager.on("start", function () {
var alice = new ContactManager.Contact({
firstName: "Alice",
lastName: "Arten",
time: "#"
});
var aliceView = new ContactManager.ContactView({
model: alice
});
ContactManager.regions.main.show(aliceView);
});
ContactManager.start();
</script>
</body>
</html>
#Edit
This code is just sample. In my real app, I have an ajax task that changes DOMs in the view. This ajax task creates a tree (jsTree) in onRender event. If i use modelEvents: {"change": "render"}, my jsTree will be reload and lost its state. So I want only update the model values in the view, others DOMs is retain.
The accepted answer to the question you pointed points to another question which has the following:
modelEvents: {
'change': "modelChanged"
},
modelChanged: function() {
console.log(this.model);
this.render();
}
And the most upvoted answer suggests the same:
modelEvents: {
'change': 'fieldsChanged'
},
fieldsChanged: function() {
this.render();
}
a comment to the most upvoted answer suggests
just {'change': 'render'} does the trick too
Which means you can do
modelEvents: {
'change': 'render'
}
So somehow you need to tell marionette invoke render on model changes.
I don't think backbone and marionette couple is smart enough to know whether you need to render view on model changes or you don't want to unless you tell them ;)

Rendering a template getting the data from a model in Backbone

I'm having some issues with rendering my view in backbone getting the data from my model so I'd appreciate any help. Here goes my html code:
<ul id="datos">
</ul>
<script type="text/template" id="listado-template">
<h2>Mi listado</h2>
<li>Item 1: <%= item1 %></li>
</script>
<script>
modelo = new Modelo();
modeloView = new ModeloView({model: modelo});
</script>
And this are my model and my view:
Modelo = Backbone.Model.extend({
urlRoot: 'myurljson',
});
Backbone.View.extend({
tagName: "ul",
el: "#datos",
template: _.template($('#listado-template').html()),
initialize: function() {
this.model.on('change', this.render, this);
},
render: function() {
this.$el.append(this.template(this.model.toJSON()));
return this;
}
});
The problem is my template is not renderized well. I'm getting an undefined error with item1. But if I delete this tag li, the tag h2 is renderized so I guess the problem is in getting my data from my model through "myurljson". Any help? Thank you!
Underscore will fail if you try to render an undefined variable. See this Fiddle trying to reproduce your problem : http://jsfiddle.net/nikoshr/PELfV/
You can
define a default item1 property in your model wit a sensible value
Modelo = Backbone.Model.extend({
urlRoot: 'myurljson',
defaults: {
item1: ''
}
});
A demo at http://jsfiddle.net/nikoshr/PELfV/1/
or test the value before printing it
<script type="text/template" id="listado-template">
<li>Item 1: <% if (typeof item1!=="undefined") print(item1) %></li>
</script>
And its demo http://jsfiddle.net/nikoshr/PELfV/2/

Underscore templating error with backbonejs [duplicate]

This question already has an answer here:
Underscore.js Template Issue - Cannot call method 'replace' of null
(1 answer)
Closed 9 years ago.
When this html code with Backbonejs is opened Chrome Java script console is throwing the following error - uncaught TypeError: Cannot call method 'replace' of undefined ,
but when i remove this one line of code containing usage of underscore templating this.template = _.template($('#listing').html())
from the List_view's initialize method its working fine . Why is the usage of underscore templating throwing the error ??
Here is the code
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Example Backbone Whisky APP</title>
</head>
<body>
<script src="LIB/json2.js"></script>
<script src="http://underscorejs.org/underscore.js"></script>
<script src="http://code.jquery.com/jquery.js"></script>
<script src="http://backbonejs.org/backbone.js"></script>
<script type = "text/template" id="listing">
<li>%= value %</li>
</script>
<script>
Whisky = Backbone.Model.extend();
firstWhisky = new Whisky({
name : 'Blenders Pride'
});
Whiskies = Backbone.Collection.extend({
Model:Whisky ,
url:"#"
});
first_view = Backbone.View.extend({
el : 'body',
initialize : function() {
this.$el.empty();
this.render();
} ,
render : function() {
this.$el.append("<h1>The Whisky APP</h1>");
this.list_view = new List_view();
this.$el.append(this.list_view.render().el);
return this ;
}
});
List_view = Backbone.View.extend({
tagName : 'ul' ,
initialize : function() {
this.template = _.template($('#listing').html());
} ,
render : function() {
this.$el.empty();
this.$el.append("<li>Royal stag</li>");
this.$el.append("<li>Signature </li> ");
return this ;
}
});
index_view = new first_view();
</script>
</body>
</html>
The problem is that your call to $("#listing").html() is returning undefined as the element isn't available yet. You'd need to wait for the DOM to have loaded to access the element by ID. You could confirm this by doing a simple alert inline. You need to delay the retrieval until the DOM is ready.
In this case, it's because you've got the script tags in the body, making them unavailable at the time that you've requested them. Move the script tags (and templates), and it will work:
http://jsbin.com/obahux/2/
One issue you'll have is that your syntax is wrong, you should be using <% and %> for executing code or emitting values:
<script type = "text/template" id="listing">
<li><%= value %></li>
</script>
That's because, in your first_view initialize function you're clearing el with this.$el.empty() that makes body empty and there is nothing in there, all scripts and templates in there will be ommited.
You can find a better solution for clearing it. or just wrap that in another div tag

template not loading in backbone.js ( TypeError: text is undefined )

I'm learning backbone.js and I'm pretty much in the beginning. I want to add a template through underscore template method but it's not working for me. I searched for this error but couldn't fix it myself. How can I move forward if it's not showing the template. Need some help guys.
Here is the code (this code is from addyosmani's book backbone-fundamentals):
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>testing</title>
</head>
<body>
<script src="scripts/jquery.js"></script>
<script src="scripts/underscore.js"></script>
<script src="scripts/backbone.js"></script>
<script>
var TodoView = Backbone.View.extend({
tagName: 'li',
// Cache the template function for a single item.
todoTpl: _.template( $('#item-template').html() ),
events: {
'dblclick label': 'edit',
'keypress .edit': 'updateOnEnter',
'blur .edit': 'close'
},
// Re-render the titles of the todo item.
render: function() {
this.$el.html( this.todoTpl( this.model.toJSON() ) );
this.input = this.$('.edit');
return this;
},
edit: function() {
// executed when todo label is double clicked
},
close: function() {
// executed when todo loses focus
},
updateOnEnter: function( e ) {
// executed on each keypress when in todo edit mode,
// but we'll wait for enter to get in action
}
});
var todoView = new TodoView();
// logs reference to a DOM element that cooresponds to the view instance
console.log(todoView.el);
If the template is defined after your script it will not work.
wrap your entry point into
$(function(){
var todoView = new TodoView();
});
so you dont get this kind of error.
I got the same error. Make sure that template with defined id exists on the page.
In my case I used wrong id for template, and this was a reason of error "TypeError: n is undefined".

Losing Scope when Repeating using View Render in Backbone.js

I'm a newbie at Backbone.js and am coming across a scope issue with a simple view & model scenario.
I've created a simple model with a single default "score" value. I also created a simple view containing a template rendered value of "score" and a button to increment score by one on each press. The view repeats the render every time the score value is changed.
I've got this to work but in a way that I think may be a botch. The template will only render the first time unless I cache the value of "this" in view variable "thisView". If I don't it seems to lose focus and the rendering errors. Is this a good idea? Or am I missing something about repeatedly applying the render.
Thanks for any advice
<!DOCTYPE html>
<html>
<head>
<title>Demo</title>
<style>
#view_container{background-color: rgba(12, 5, 11, 0.14);width: 100px;height: 100px;padding: 10px;}
</style>
</head>
<body>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js"></script>
<script src="http://ajax.cdnjs.com/ajax/libs/underscore.js/1.1.4/underscore-min.js"></script>
<script src="http://ajax.cdnjs.com/ajax/libs/backbone.js/0.3.3/backbone-min.js"></script>
<!-- View Template -->
<script type="text/template" id="view-template">
<div class="profileSpace">
<p>Score: <%= score %></p>
</div>
<button id="increaseScoreButton">Increase Score</button>
</script>
<div id="view_container"></div>
<script type="text/javascript">
(function ($) {
MyModel = Backbone.Model.extend({
defaults:{
score:0
},
initialize: function(){
},
increaseScore: function(){
//Increase Score by 1
var currentScore = this.get("score");
var newScore = currentScore +1;
this.set({score:newScore});
}
});
MyView = Backbone.View.extend({
el: $("#view_container"),
template: _.template($('#view-template').html()),
initialize: function(model){
thisView =this;
this.model.bind('change', this.render, this);
this.render();
},
events: {
"click #increaseScoreButton": "increaseScore"
},
increaseScore: function(){
this.model.increaseScore();
},
render: function(){
var currentScore = thisView.model.get("score");
var html = thisView.template({"score":currentScore});
$(thisView.el).html( html );
return thisView;
}
});
myModel = new MyModel;
myApp = new MyView({model:myModel});
})(jQuery);
</script>
</body>
</html>
You bind the change event via this.model.bind('change', this.render, this);
This syntax was introduced in Backbone 0.5.2 but you use Backbone 0.3.3 in your example.
0.5.2 — July 26, 2011
The bind function can now take an optional third argument to specify the this of the callback function.
Upgrade Backbone to a more recent version (0.9.2 as of today) and you should get the expected behaviour.
Or, as CoryDanielson pointed out in the comments, you could use _.bindAll to have a guaranteed context:
MyView = Backbone.View.extend({
initialize: function(model) {
_.bindAll(this, 'render');
this.model.bind('change', this.render);
this.render();
},
render: function(){
var currentScore = this.model.get("score");
var html = this.template({"score":currentScore});
$(this.el).html( html );
return this;
}
});

Resources