RSS

Tag Archives: express.js

I’m starting to wear Mustaches

It sounds easy, but the recipe includes Mustache/Handlebars Jade and un-named arrays of items 🙂

Who renders?

I love the Jade syntax and it’s natural to me to use it in the Express.js workflow. You write (clean!) templates, the middleware does the rest.
Everything looks good but I was missing a template engine for javascript objects. I used Angular.js but it is a fence too tight to me (I happily embrace the single responsibility principle).

So I tried Handlebars and (with a couple of tweaks) it works like a charm! Just remember the workflow:

  • Express.js renders (server-side) the Jade template into plain html
  • the browser renders (client-side) the Handlebars template previously generated

How

  1. assign to the container tag a custom attribute (I use something like “< ul handlebars=users …“)
  2. write the handlebar template inside the container
  3. bind the javascript context to the data attribute of the container ($(“[handlebars=users]”).data([…])). Please note I’m using an array
  4. render the whole thing

The render engine

This is easy: take the data, take the html, mix together, done.

 $("[handlebars=users]").data("hbar", [
  { _id:1, name:"test 1" }
  , { _id:2, name:"test 2" }
  , { _id:3, name:"test 42" }
]);

(..)

$(document).ready(function() {
  $("[handlebars]").each(function(i,o) {
    var $o = $(o);
    var data = $o.data();
    var template = Handlebars.compile($o.html());
    $o.html(template(data));
  });
});

The previous code doesn’t work very well with json over web-services and late bindings, so I built a function to do this:

function handlebar_bind($elem, url) {
  if ($elem && $elem.length>=0) {
    if (typeof url == "string") {
      $.ajax({
        url: url,
        //jsonp: "callback",
        //dataType: "jsonp",
        dataType: "json",
        success: function(data) {
          var template = Handlebars.compile($elem.html());
          $elem.html(template(data));
        },
        error: function(XHR, textStatus, errorThrown) {
          console.log(XHR);
          console.log(textStatus);
          console.log(errorThrown);
        }
      });
    }
    else { // url is an object or array
      var template = Handlebars.compile($elem.html());
      $elem.html(template(url));
    }
  }
}

Repeaters

Do you remember we bound an array to the html tag? Now you can use the built-in each helper, remembering that this and . refers to the context’s item.
I’ll do the binding via the following script:

<ul>
{{#each .}}
  <li>{{this.name}}</li>
{{/each}} 
</ul>

I also found this syntax (more readable):

{{#each . as |user|}}
 ..
 <li>{{user.name}}</li>
 ..

…and Jade?

The safest way to add a handlebar template to the Jade syntax is to use comments:

div(handlebars="mylist")
  // {{#each .}}
  span {{this}}
  // {{/each}} 

It will be rendered as an html comment and it will not hurts your html. I do prefer comments because they don’t break the DOM (i.e inside a table BUT outside a td), but many use plain text instead:

| {{#each .}}
Advertisements
 
Leave a comment

Posted by on 2015/06/16 in dev

 

Tags: , , , ,

Express.js and jsonp

Express.js has a very good jsonp handler, the key is to use it in the right way =)

The first step is to ensure the callback name. The default value is “callback” so on a res.jsonp(..) the server will look for req.query[“callback”] to build the response.
This value can be overridden with an app.set(‘jsonp callback name’,..).

app.js:

app.get('/', function(req, res) {
  var jsonp_callback = app.get('jsonp callback name');
  var jsonp = (req.query[jsonp_callback]);
  var result = [{},{},.....];
  if (jsonp) res.jsonp(result);
  else res.json(result);
});

jQuery

When asking for jsonp stuff, jQuery will handle the whole request/response stuff.
We just need to say the dataType and the callback key.

Here’s an example of the client side call:

$.ajax({
  url: "http://localhost:3000/",
  jsonp: "callback",
  dataType: "jsonp",
  success: function( response ) {
    console.log( response );
  },
  error: function(XHR, textStatus, errorThrown) {
    console.log(XHR);
    console.log(textStatus);
    console.log(errorThrown);
  }
});

AngularJS

Angular will expect the callback will be named “JSON_CALLBACK” so we have to use it this way:

$http.jsonp('http://localhost:3000?callback=JSON_CALLBACK')
  .success(function(data, status, headers, config) {
    console.log( data );
  })
  .error(function(data, status, headers, config) {
    console.log(data);
    console.log(status);
  });
 
Leave a comment

Posted by on 2015/02/04 in dev

 

Tags: , , , ,