3
votes

Ok, I am playing around with Backbone, node.js, Underscore, Backbone Boilerplate so I have enough knowledge. Been asking questions like crazy as I still can't quite get my head around it. I am currently attempting to use the Underscore library with Backbone Boilerplate to make a very simple template which will allow me to pass in data; then when the model is updated, change the view which would change the template. I believe this is the correct way of doing it, instead of writing HTML code inside my JS file? Stop me if I'm wrong.

The Backbone Boilerplate has its template .fetch() system which I understand. However it would mean writing HTML in my JS I believe. So I wanted to use Underscore to simply pass information from the model to the view to the modules to render the template again (or I might be able to skip the view completely?).

My question is why won't this work, I think it's because I'm not changing it to JSON.

My HTML template:

<div>
    <script id="rtemp" type="text/x-underscore-template">
        <span><%= title %></span>
    </script>​
</div>

And the JavaScript:

define([
  // Global application context.
  "app",

  // Third-party libraries.
  "backbone",
  "underscore",
  "json2"
],

function(app, Backbone) {
  var Attempt = app.module();

  Attempt.Model = Backbone.Model.extend({});
  Attempt.Collection = Backbone.Model.extend({});

  Attempt.Views.Tutorial = Backbone.View.extend ({
    template: "app/templates/attempt",
    render: function(done) {
      var tmpl = app.fetchTemplate(this.template);
      //console.info(tmpl);
      this.$el.html(tmpl({title: 'This is a title'}))
    }
  });

  return Attempt;
});

When I inspect the element it shows in the <div> however it still has the template script tags around it so doesn't show on the page in HTML. I tried using json2 to convert it to JSON first, but that didn't seem to work unless I did something wrong. Is Underscore the best thing to use? I assumed so as it's a Backbone dependency. Or should I use something else. I just want to avoid writing HTML in my JS.

1

1 Answers

4
votes

If I understand you right, you're ending up with this HTML:

<div>
    <script id="rtemp" type="text/x-underscore-template">
        <span>This is a title</span>
    </script>​
</div>

That's the right behavior based on the code you're using but that's clearly not the result you want.

The <script> wrapper for templates is used when you're embedding the template inside an HTML page. This is done so that the browser won't try to interpret your template as HTML and to keep the browser from trying to render it on its own. In such cases, you'd have the template embedded in the HTML page like this:

<!-- Some HTML stuff... -->
<script id="rtemp" type="text/x-underscore-template">
    <span><%= title %></span>
</script>​
<!-- Some other HTML stuff... -->

and you'd use it like this:

var t    = _.template($('#rtemp').html());
var html = t(...)

The $('#rtemp').html() part extracts just the content of the template's <script> wrapper so _.template would only see <span><%= title %></span> and the final processed template would just be a simple <span>. For example: http://jsfiddle.net/ambiguous/dzPzC/

In your case, you're reading the entire <div><script>...</script></div> as the template and feeding that to _.template. The result is that tmpl({title: 'This is a title'}) still includes the <script>, the browser doesn't know what to do with a <script type="text/x-underscore-template"> so the <span> that you're interested in doesn't get rendered at all.

You don't need the <script> wrapper at all, that's only needed when you're embedding a raw template inside some HTML. Your template only needs the the content of your <script>:

<span><%= title %></span>

Demo: http://jsfiddle.net/ambiguous/QuwSX/

The argument that you're passing to the template function:

tmpl({ title: '...' })

is fine, the compiled template function just wants to see a JavaScript object. People talk about passing it JSON and often use the toJSON method to prepare data for the template but that's an abuse of terminology; the template really wants an object and JSON is, technically, a string.