Quantcast
Channel: Dumitru Glavan » javascript
Viewing all articles
Browse latest Browse all 10

Asynchronous Template Loading With tmpload jQuery Plugin and Backbone.js

$
0
0

I prefer keeping my “views” on the frontend side when building a Single Page Application. I use templates to update data on a certain portion of my interface. Using templates gives you the advantage to isolate your logical Javascript code from your presentational part. So, instead of inserting text data into the DOM directly from your View clases like this:

  $('#main').html('<p>Ugly mixed text with code.</p><div>Hello!</div>')

You load a template that you defined earlier and assigned an id to it:

<script type="text/template" id="my-template">
  <p>Ugly mixed text with code.</p>
  <div>Hello {name}!</div>
</script>

Later then, you grab the template and display it:

  $('#main').html($('#my-template').html().replace('{name}', 'Dumitru'));

You can even use a template engine like jQuery Template, Mustache or Underscore.js to pull some variables in your templates and make them more useful. I prefer working with Underscore.js that implements the John Resig’s Microtemplate engine and it plays well with Backbone.js. For that I adjust my template syntax to the Underscore API:

<script type="text/template" id="my-underscore-template">
  <p>Ugly mixed text with code.</p>
  <div>Hello <%=name %>!</div>
</script>

And load my template with the _.template function:

  var compiled = _.template($('#my-underscore-template').html());
  $('#main').html(compiled({name : 'Dumitru'}));

The technic, sounds really nice – you keep the template in your DOM structure and only pick it up when you need it and load you content. The only problem is that when you have a lot of templates, your DOM structure keeps growing and growing and becomes ugly, heavy and hard to maintain. Another problem is that you keep a couple of templates in your DOM that probably the user won’t use them (i.e. templates for editing user details). Wouldn’t it be better to keep the templates in separate files and load them only when you need them? That’s exactly what the jQuery tmpload plugin does for you.

Usually I keep my templates in separate .html files in the public path:

  /public
    /templates
      /users
        login.html
        register.html
        edit.html
      /posts
        view.html
        comment.html
        edit.html

Basically you organize your templates however suits you most. After you created your template and dropped the HTML structure inside, you can load it with tmpload and reuse it:

  $.tmpload({
    url: '/templates/posts/view.html',
    tplWrapper: _.template,
    onLoad: function (compiledTpl) {
      $('#main').html(compiledTpl({name : 'Dumitru'}));
    }
  });

In the example above I load my template from a certain URL and also pass my template engine object to it. This way my plugin will compile the template automatically and send me back the template object that I can use in my onLoad callback. Executing the code in the onLoad callback assures you that the template is there.

Another important thing to notice is that the plugin caches the template so next time when you load the same template it doesn’t do a request to the server to grab it, it keeps it into a variable $.tmpload.templates.

You can still keep you template in your DOM structure and load it with the plugin. This way you don’t even need to execute your code in a callback because you don’t have asynchronous stuff going on:

  var compiledTpl = $.tmpload({
    id: 'my-underscore-template',
    tplWrapper: _.template
  });
  $('#main').html(compiledTpl({name : 'Dumitru'}));

When the template is in the DOM, it loads instantly and gets returned by the plugin. But I recommend using it with the onLoad callback, because it’s easier to refactor it latter when you switch to remote templates.

You also have the ability to set some default options to the plugin, so you don’t specify them latter:

  // somewhere in your app bootstrap
  $.tmpload.defaults.tplWrapper = _.template;

  // then in your code you don't have to specify the template engine anymore
  var compiledTpl = $.tmpload({
    id: 'my-underscore-template'
  });
  $('#main').html(compiledTpl({name : 'Dumitru'}));

Bellow is an example about how I use the templates in my Backbone Views (it’s CoffeeScript code):

  # somewhere in my bootstrap.js file
  $.tmpload.defaults.tplWrapper = _.template


  # then in my View
  class UserView extends Backbone.View
    tplUrl: '/templates/posts/view.html'

    render: ()->
      $el = $(@el)
      userModel = @model
      $.tmpload
        url: @tplUrl
        onLoad: (compiledTpl)->
          htmlData = compiledTpl({user: userModel})
          $el.html(htmlData)


  # after this I instantiate the view in my router
  userView = new UserView()
  userView.render()

If you want to load some templates from the DOM, you can tweak your view like this:

  # then in my View
  class UserView extends Backbone.View
    tplId: 'my-underscore-template'

    render: ()->
      $el = $(@el)
      compiledTpl = $.tmpload
        id: @tplId
      htmlData = compiledTpl({user: @model})
      $el.html(htmlData)

tmpload is a powerful plugin to use along with your SPA. I hope you’ll enjoy it.


Viewing all articles
Browse latest Browse all 10

Trending Articles