Skip to content

Getting Started In Backbone

chrisdickinson edited this page Jan 19, 2012 · 2 revisions

Getting Started / In Backbone

Backbone is a fairly popular Javascript MVC-thingy that commonly uses templates to render the views. Integrating Plate into Backbone is easy, which has the pleasant side-effect of asynchronous renders, ensuring that no one view holds up the show.

Build

Build Plate in the same manner as suggested on Getting Started / in Browser.

Integration

Bring in the necessary scripts, and setup a template using type="text/html":

<script type="text/javascript" src="/js/underscore-1.3.0.min.js"></script>
<script type="text/javascript" src="/js/backbone-0.5.3.min.js"></script>
<script type="text/javascript" src="/js/plate.js"></script>
<script id="entry-template" type="text/html">
  <h2>{{ title|capfirst }}</h2>

  <p>
    {{ content|linebreaks }}
  </p>

  <div class="meta">
    Posted on {{ pub_date|date:"F j, Y" }} by {{ user.username }}.
  </div>
</script>

In your code (which can be included inline in a script tag:

  // Use this loader (from https://github.com/chrisdickinson/plate/wiki/Getting-Started---In-Browser)
  // to make ``include`` & ``extends`` work with ``<script type="text/html">`` style tags.
  plate.Template.Meta.registerPlugin(
    'loader',
    function(templateName, ready) {
      var target = $('#'+templateName);
      if(target.length) {
        ready(null, new plate.Template(target.text()));
      } else {
        ready(new Error('Could not find '+templateName));
      }
    }
  )

  window.BlogEntryView = Backbone.View.extend({
    // Different here!
    template: new plate.Template('{% extends "entry-template" %}'),

    // Normal...
    tagName: 'div',
    className: 'entry',

    initialize: function() {
      _.bindAll(this, 'render');
    },

    // Different here too!
    render: function() {
      var self = this;
      this.template.render(this.model.toJSON(), function(err, data) {
        $(self.el).html(data);
      });
      return this;
    }
  });

  // You'd do something better abstracted, but for example purposes...
  var entry = new window.Entry({id: 35});
  entry.fetch({
    success: function(model, response) {
      // The newly-fetched & populated entry.
      var be = new window.BlogEntryView({model: model});
      // The append happens immediately, so the element is there but may not be done rendering
      // yet. However, when it finishes, since it was passed by reference, it will be updated
      // in the DOM.
      $('#content').append(be.render().el);
    }
  });

There are important bits here. The first is the new plate.Template('{% extends "entry-template" %}') (which loads the template source from the <script id="entry-template" type="text/html"> tag).

The second is the actual rendering. Like normal, we hand the template the models. Because there's a callback involved (remember, Plate is asynchronous), we lose this when we enter the callback, so we use the closure & stash this into the self variable for later use. Once we're in the callback, we've got the rendered data which we can inject into the element with the $(self.el).html(...) call.