Validating template variables in JavaScript

Is there a best case practice for validating when using a templating engine?

I'm currently building a site with node.js and couchdb, and I'm using express with ejs as a framework and templating engine respectively. It's possible that I end up with [Object object] or undefined spelled out literally in my HTML. I can try to validate in couch with a validate_doc_update function, or in node inside my routing function before I render to the template, or right in the ejs template. Which one of these or all of these should I do?

I suggest writing a function to take your template context object and prepare it for rendering. These are sometimes called presenter functions and/or the presenter pattern. You would use this from your node.js routing function before your render the template. This function could replace null/undefined with empty string and also detect objects whose toString is "[Object object]" or otherwise undesired and replace them with empty string as well. It is easy to write unit tests for this and will prevent you from having to duplicate logic in many templates. This function should recursively walk an entire object graph or array of object graphs.

You may also want other functionality like abbreviating abnormally long strings. For example, if someone accidentally pastes in a bunch of garbage into the "firstName" field of your user object and this is over some sane limit of say 100 characters, your presenter function could truncate it and append an ellipsis. Just another example of this data cleanup or "presentation" type logic.

Otherwise, you need expressions like <%= someObj.someProp || '' %> in your ejs templates which will cause lots of boilerplate code duplication.

Here's a first-cut working jsfiddle implementation (uses underscore.js).

function sanitize(context) {
    if (Array.isArray(context)) {
      return _.map(context, sanitize);
    }
    _.each(context, function (value, key) {
        if (value === null) {
          context[key] = "";
          return;
        }

        switch (typeof value) {
          case "object":
            context[key] = sanitize(value);
            break;
          case "number":
            //No-op
            break;
          case "boolean":
            //No-op
            break;
          default:
            context[key] = value || ""; //handles undefined
        }                
    });
    return context;
}