简体   繁体   中英

Handlebars.js - Building a Template Template

TL;DR

In the following Handlebars template...

<div class="field field-label">
  <label>{{label}}</label><input type="text" value="{{{{attribute}}}}">
</div>

I need {{attribute}} to be evaluated but value="{{ value of attribute }}" to be printed.

Background

I've got an interesting use for templating. My application has dozens of forms (and growing!), and several ways to display them. Obviously they can be displayed in the browser, or a mobile device, or a PDF, etc... So what I'd like to do is define these forms in JSON to live somewhere like MongoDB. That way, they can be easily modified without the HTML views, mobile apps, and PDF render function all being updated.

{
  title: 'Name of this Form',
  version: 2,
  sections: [
    { 
      title: 'Section Title',
      fields: [
        {
          label: 'Person',
          name: 'firstname',
          attribute: 'FIRST',
          type: 'text'
        }, {
          label: 'Birthday',
          name: 'dob',
          attribute: 'birthday',
          type: 'select',
          options: [
            { label: 'August' },
            { label: 'September' },
            { label: 'October' }
          ]
        },
        ...
        ...

That's a taste. So type: 'text' results in <input type="text"> , name is the name of the input, attribute is the attribute from the model, yada yada. It gets fairly complex with nested optional forms, but you get the point.

The problem is, now I've got two contexts . The first being the JSON with the form data, and the second being the JSON from the model. I've got two options I think would work well.

Solution 1

Quick little closure containing the model context registered as a helper.

var fn = (function(model) {
  return function(attr) {
    return model[attr]
  }
})(model);

Handlebars.registerHelper('model', fn)

...to be used like so...

<input type="text" name="{{name}}" value="{{model attribute}}">

Solution 2

Two passes. Have my template output a template that I can then compile and run with my model. One big advantage, I can precompile the forms. I would prefer this approach. Here's my question. How do I print out {{attribute}} from my templates?

For example, in my text template...

<div class="field field-label">
  <label>{{label}}</label><input type="text" value="{{{{attribute}}}}">
</div>

I need {{attribute}} to be evaluated and {{ value of attribute }} to be printed.

I went with solution 2, kinda. It was important to me that I could precompile the forms sans data. So what I did was just add a few helper functions...

Handlebars.registerHelper('FormAttribute', function(attribute) { 
  return new Handlebars.SafeString('{{'+attribute+'}}');    
});

Handlebars.registerHelper('FormChecked', function(attribute) {
  return new Handlebars.SafeString('{{#if ' + attribute + '}}checked="checked"{{/if}}');
});

...that I could use in my form templates...

<input type="text" name="{{name}}" value="{{FormAttribute attribute}}">

...that results in...

<input type="text" name="FirstName" value="{{FirstName}}">

I would still be interested to learn if there's some way to have Handlebars ignore and not parse curly brackets {{}} without using helpers.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM