I have been looking over and found alot of answers but none seem to work.
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>
Shopping Cart
</title>
<link rel="stylesheet" href="lib/style.css" type="text/css">
</head>
<body>
<script id="rtemp" type="text/x-underscore-template"">
<span><%= title %></span>
</script>
<script src="lib/jquery.js" type="text/javascript"></script>
<script src="lib/underscore.js" type="text/javascript"></script>
<script src="lib/backbone.js" type="text/javascript"></script>
<script src="lib/script.js" type="text/javascript"></script>
</body>
<script>
var Photo = Backbone.Model.extend({
initialize: function(){
console.log('this model has been initialized');
this.bind("change:title", function(){
var title = this.get("title");
console.log("My title has been changed to.. " + title);
var pv = new PhotoView();
pv.render();
});
},
setTitle: function(newTitle){
this.set({ title: newTitle });
},
setLocation: function(newLoc)
{
this.set({location:newLoc});
}
});
var PhotoView = Backbone.View.extend
({
el: $('body'),
render: function(event)
{
var name = myPhoto.get('title');
console.info(name);
var template = _.template($('#rtemp').html(), {title:name});
console.info(this.model);
$(this.el).html(template);
return this;
}
});
</script>
</html>
First;
Create a new instance of the method
var newPhoto = new Photo();
newPhoto.setTitle('Fishing');
This work fine, it will load into the body via the template. However if i then do it again,
newPhoto.setTitle('Sailing');
I get the error - "Cannot call method 'replace' of null"
No line error but I believe it is at
var template = _.template($('#rtemp').html(), {title:name});
You have a few things wrong here.
Your template has a double
"
in thetype
attribute, it should be:Your view's
render
is referencingmyPhoto
when it should bethis.model
:And your main problem is that your view uses
<body>
as itsthis.el
and your template is inside<body>
.You completely replace the content of
<body>
when you render your view:so after the first
render
call, there is no more#rtemp
. Then, on the nextrender
call, you try this:but since
#rtemp
isn't in the DOM anymore, everything falls apart.If you grab the template immediately:
and then use
this.template()
inrender
:you'll have better luck. You will, of course, need to make sure that you define your view inside a document-ready handler with this approach or
#rtemp
might not be available when you define your view.Demo: http://jsfiddle.net/ambiguous/dwGsM/
That said, the structure of your application is rather bizarre. You have a model which listens to itself and then the model creates and renders a view when something changes. A model listening to itself is fine in itself but usually you have views listening to models and the view would re-render itself (or just parts of itself) as the model changes.
Your model should look more like this:
And then your view like this:
The
_.bindAll
ininitialize
ensures thatthis.render
will be called with the rightthis
; theninitialize
binds to the event so that it can respond to changes in the model. The view knows what it cares about so it is responsible for dealing with changes in the model. And in therender
, you usually just calltoJSON
to get the data for the template. Also, newer versions of Backbone include a cached version of$(this.el)
in the view asthis.$el
so you don't have to$(this.el)
yourself anymore.Then you'd crank things up like this:
You tell the view what model to use by specifying the
model
option when creating the view.You might also want to move the template
<script>
out of<body>
.New and Improved Demo: http://jsfiddle.net/ambiguous/Kytw7/