Template Strategies

Creating HTML markup is a lot of what we do as front end developers. There are many solutions as evident by the ever increasing number of templating libraries found on the web, and Giraffe aims to easily support the common cases and be flexible enough to support any form of templating. Giraffe provides templating strategies based on the built-in dependecies of Backbone, namely the Underscore template function. Selecting a strategy tells Giraffe how to utilize the Giraffe.View#template property when rendering a view. The predefined strategies are:

Templating is fully user customizable as detailed in the User-Defined Template Strategy and Mustache Integration sections below.

At Barc we love CoffeeScript and use funcd, a function based template engine.

Strategy Scope

First decide whether to set the strategy globally or to a specific view. The global case is the one most used as it enforces consistent templating across a project. To set a global strategy use the class method Giraffe.View.setTemplateStrategy.

Giraffe.View.setTemplateStrategy('underscore-template');

To enable for a specific view, set the templateStrategy option.

var View = Giraffe.View.extend({
  templateStrategy: 'underscore-template',
  template: '<p>Hello <%= name %></p>',
  serialize: function() {
    return {name: 'giraffe'};
  }
  ...
});
The template property works in concert with serialize to transform a view's data into HTML when using one of the predefined strategies. By default, serialize returns the view.

Template Strategy 'underscore-template'

This is the simplest strategy and works well with CoffeeScript's multi-line strings.

Giraffe.View.setTemplateStrategy('underscore-template');

var View = Giraffe.View.extend({
  // Optionally, set the strategy for this view only
  //templateStrategy: 'underscore-template',
  template: '<p>Using the \'<%= name %>\' strategy</p>',
  // or
  //template: $('#my-template-selector').html(),
  // or
  //template: function() { return '<p><%= name %></p>'; },
  serialize: function() {
    return {name: 'underscore-template'};
  }
});

var view = new View();
view.attachTo('body');

Result

Giraffe.View.setTemplateStrategy('underscore-template');

var View = Giraffe.View.extend({
  // Optionally, set the strategy for this view only
  //templateStrategy: 'underscore-template',
  template: '<p>Using the \'<%= name %>\' strategy</p>',
  // or
  //template: $('#my-template-selector').html(),
  // or
  //template: function() { return '<p><%= name %></p>'; },
  serialize: function() {
    return {
      name: 'underscore-template'
    };
  }
});

var view = new View();
view.attachTo('body');
<!DOCTYPE html>
<html>
  <head>
    <link rel='stylesheet' type='text/css' href='../css/reset.css' />
    <link rel='stylesheet' type='text/css' href='templatestrategies0-style.css' />
  </head>
  <body>
    <script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.4.4/underscore-min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/backbone.js/1.0.0/backbone-min.js"></script>
<script src="../backbone.giraffe.js" type="text/javascript"></script>
    <script type='text/javascript' src='templatestrategies0-script.js'></script>
  </body>
</html>
p {
  color: #F50;
  font-size: 18px;
}

Template Strategy 'underscore-template-selector'

This strategy expects a selector to a DOM element containing the template. This is the default template strategy because it is concise and a common choice of Backbone developers.

In HTML page

<script id='hello-template' type='text/template'>
  <p>Using the '<%= name %>' strategy</p>
</script>

In script


Giraffe.View.setTemplateStrategy('underscore-template-selector');

var View = Giraffe.View.extend({
  // Optionally, set the strategy for this view only
  //templateStrategy: 'underscore-template-selector',
  template: '#hello-template',
  serialize: function() {
    return {name: 'underscore-template-selector'};
  }
});

var view = new View();
view.attachTo('body');

Result

Giraffe.View.setTemplateStrategy('underscore-template-selector');

var View = Giraffe.View.extend({
  // Optionally, set the strategy for this view only
  //templateStrategy: 'underscore-template-selector',
  template: '#hello-template',
  serialize: function() {
    return {
      name: 'underscore-template-selector'
    };
  }
});

var view = new View();
view.attachTo('body');
<!DOCTYPE html>
<html>
  <head>
    <link rel='stylesheet' type='text/css' href='../css/reset.css' />
    <link rel='stylesheet' type='text/css' href='templatestrategies1-style.css' />
  </head>
  <body>
    <script id='hello-template' type='text/template'>
  <p>Using the '<%= name %>' strategy</p>
</script>

<script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.4.4/underscore-min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/backbone.js/1.0.0/backbone-min.js"></script>
<script src="../backbone.giraffe.js" type="text/javascript"></script>
    <script type='text/javascript' src='templatestrategies1-script.js'></script>
  </body>
</html>
p {
  color: #F50;
  font-size: 18px;
}

Template Strategy 'jst'

This strategy expects template to be a function that returns an HTML string.

Giraffe.View.setTemplateStrategy('jst');

var View = Giraffe.View.extend({
  // Optionally, set the strategy for this view only
  //templateStrategy: 'jst',
  template: function(data) {
    return '<p>Using the \'' + data.name + '\' strategy</p>';
  },
  serialize: function() {
    return {name: 'jst'};
  }
});

var view = new View();
view.attachTo('body');

Result

Giraffe.View.setTemplateStrategy('jst');

var View = Giraffe.View.extend({
  // Optionally, set the strategy for this view only
  //templateStrategy: 'jst',
  template: function(data) {
    return '<p>Using the \'' + data.name + '\' strategy</p>';
  },
  serialize: function() {
    return {
      name: 'jst'
    };
  }
});

var view = new View();
view.attachTo('body');
<!DOCTYPE html>
<html>
  <head>
    <link rel='stylesheet' type='text/css' href='../css/reset.css' />
    <link rel='stylesheet' type='text/css' href='templatestrategies2-style.css' />
  </head>
  <body>
    <script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.4.4/underscore-min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/backbone.js/1.0.0/backbone-min.js"></script>
<script src="../backbone.giraffe.js" type="text/javascript"></script>
    <script type='text/javascript' src='templatestrategies2-script.js'></script>
  </body>
</html>
p {
  color: #F50;
  font-size: 18px;
}

User-Defined Template Strategy

To completely override Giraffe templating, assign a function to templateStrategy that returns an HTML string.

As an example, many developers have a build process to precompile templates into JavaScript Templates (JST) objects. The object might look something like this:

var JST = {
  body: function(it) {
    return '<p>Using a ' + it.name + ' strategy</p>';
  },
  header: function(it) { return '<div>Header</div>'; },
  footer: function(it) { return '<div>footer</div>'; },
};

To use this JST, we'll assign setTemplateStrategy a function which uses the view's template as the name of JST function to call.


Giraffe.View.setTemplateStrategy(function() {
  var data = this.serialize();
  var template = JST[this.template];
  return template(data);
});

var View = Giraffe.View.extend({
  template: 'body',
  serialize: function() {
    return {name: 'user-defined'};
  }
});

var view = new View();
view.attachTo('body');

Result

var JST = {
  body: function(it) {
    return '<p>Using a ' + it.name + ' strategy</p>';
  },
  header: function(it) {
    return '<div>Header</div>';
  },
  footer: function(it) {
    return '<div>footer</div>';
  },
};


Giraffe.View.setTemplateStrategy(function() {
  var data = this.serialize();
  var template = JST[this.template];
  return template(data);
});

var View = Giraffe.View.extend({
  template: 'body',
  serialize: function() {
    return {
      name: 'user-defined'
    };
  }
});

var view = new View();
view.attachTo('body');
<!DOCTYPE html>
<html>
  <head>
    <link rel='stylesheet' type='text/css' href='../css/reset.css' />
    <link rel='stylesheet' type='text/css' href='templatestrategies3-style.css' />
  </head>
  <body>
    <script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.4.4/underscore-min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/backbone.js/1.0.0/backbone-min.js"></script>
<script src="../backbone.giraffe.js" type="text/javascript"></script>
    <script type='text/javascript' src='templatestrategies3-script.js'></script>
  </body>
</html>
p {
  color: #F00;
  font-size: 18px;
}

Mustache Integration

This example shows how to integrate Mustache templates into Giraffe using a user-defined strategy.

Giraffe.View.setTemplateStrategy(function() {
  return Mustache.render(this.template, this.serialize());
});

var View = Giraffe.View.extend({
  // Optionally, set the strategy for this view only
  //templateStrategy: function() { return Mustache.render(...); },
  template: '<p>Using {{name}}</p>',
  serialize: function() {
    return {name: 'Mustache'};
  }
});

var view = new View();
view.attachTo('body');

All we need now is a reference to the Mustache library in our page

<script src="https://cdnjs.cloudflare.com/ajax/libs/mustache.js/0.7.2/mustache.min.js"></script>

Result

Giraffe.View.setTemplateStrategy(function() {
  return Mustache.render(this.template, this.serialize());
});

var View = Giraffe.View.extend({
  // Optionally, set the strategy for this view only
  //templateStrategy: function() { return Mustache.render(...); },
  template: '<p>Using {{name}}</p>',
  serialize: function() {
    return {
      name: 'Mustache'
    };
  }
});

var view = new View();
view.attachTo('body');
<!DOCTYPE html>
<html>
  <head>
    <link rel='stylesheet' type='text/css' href='../css/reset.css' />
    <link rel='stylesheet' type='text/css' href='templatestrategies4-style.css' />
  </head>
  <body>
    <script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.4.4/underscore-min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/backbone.js/1.0.0/backbone-min.js"></script>
<script src="../backbone.giraffe.js" type="text/javascript"></script>

<script src="https://cdnjs.cloudflare.com/ajax/libs/mustache.js/0.7.2/mustache.min.js"></script>
    <script type='text/javascript' src='templatestrategies4-script.js'></script>
  </body>
</html>
p {
  color: #F00;
  font-size: 18px;
}