Handlebars

Лекция 13

Handlebars

  • шаблонизатор
  • развитие Mustache
  • Node.js, Chrome, Firefox, Safari 5+, Opera 11+, IE 6+
  • http://handlebarsjs.com/

Hello World

Hello World


npm install handlebars
    

Hello World


// hello.hbs
<div class="entry">
  <h1>
    {{title}}
  </h1>
  <div class="body">
    {{body}}
  </div>
</div>
    

Hello World


const source = // читаем hello.hbs

const template = Handlebars.compile(source);

const result = template({
  title: 'Hello World',
  body: 'First handlebars template',
});

// записываем hello.html
    

Hello World


// hello.html
<div class="entry">
  <h1>
    Hello World
  </h1>
  <div class="body">
    First handlebars template
  </div>
</div>
    

Expressions

Expressions


<h1>{{title}}</h1>
    

Expressions


<h1>{{article.title}}</h1>
    

Expressions


Идентификаторы не могут содержать:

Пробел ! " # % & ' ( ) * + , . / ;
< = > @ [ \ ] ^ ` { | } ~
    

Expressions


Но всё таки могут:

{{articles.[10].[published at]}}
{{articles.[10].[#author]}}
    

Expressions


{{foo}}
{{{foo}}}

&lt;b&gt;Hello&lt;/b&gt;
<b>Hello</b>
    

Helpers

Helpers - If


<div class="entry">
  {{#if author}}
    <h1>{{author.firstName}} {{author.lastName}}</h1>
  {{/if}}
</div>
    

Helpers - If-Else


<div class="entry">
  {{#if author}}
    <h1>{{author.firstName}} {{author.lastName}}</h1>
  {{else}}
    Author unknown
  {{/if}}
</div>
    

Helpers - If-Else-If


<div class="entry">
  {{#if author}}
    ...
  {{else if authorLegacy}}
    ...
  {{else}}
    ...
  {{/if}}
</div>
    

Helpers - Unless


<div class="entry">
  {{#unless author}}
    Author unknown
  {{/unless}}
</div>
    

Helpers - Each


<ul class="people_list">
  {{#each people}}
    <li>{{this}}</li>
  {{/each}}
</ul>
    

{
  people: [
    "Yehuda Katz",
    "Alan Johnson",
    "Charles Jolley"
  ]
}
    

Helpers - Each-Else


{{#each paragraphs}}
  <p>{{this}}</p>
{{else}}
  <p class="empty">No content</p>
{{/each}}
    

Helpers - Each-Index


{{#each array}}
  {{@index}}: {{this}}
{{/each}}
    

Helpers - Each-Key


{{#each array}}
  {{@key}}: {{this}}
{{/each}}
    

Helpers - Each-First-Last


{{#each array}}
  {{#if @first}}
    ...
  {{else if @last}}
    ...
  {{else}}
    ...
  {{/if}}
{{/each}}
    

Helpers - Each-As


{{#each array as |value key|}}
  {{#each child as |childValue childKey|}}
    {{key}} - {{childKey}}. {{childValue}}
  {{/each}}
{{/each}}
    

Helpers - With


{{#with author}}
  <h2>By {{firstName}} {{lastName}}</h2>
{{/with}}
    

Helpers - With-Else


{{#with author}}
  <p>{{name}}</p>
{{else}}
  <p class="empty">No content</p>
{{/with}}
    

Helpers - With-As


{{#with author as |myAuthor|}}
  <h2>By {{myAuthor.firstName}} {{myAuthor.lastName}}</h2>
{{/with}}
    

Helpers - Lookup


{{#each bar}}
  {{lookup ../foo @index}}
{{/each}}
    

Helpers - Log


{{log "Look at me!"}}
    

Helpers - Path


{{#each comments}}
  <h2>Comment for {{../title}}</h2>
  <div>{{body}}</div>
{{/each}}
    

Helpers - Root


{{#each comments}}
  <h2>Comment for {{@root.title}}</h2>
  <div>{{body}}</div>
{{/each}}
    

Partials

Partials


Handlebars.registerPartial(
  'myPartial',
  '{{name}}'
)
    

Partials


{{> myPartial }}
    

Partials - Dynamic Name


{{> (whichPartial) }}
    

Partials - Dynamic Context


{{> myPartial myOtherContext }}
    

Partials - Parameters


{{> myPartial parameter=value }}
    

Partials - Blocks


{{#> myPartial }}
  Failover content
{{/myPartial}}
    

Partials - Blocks


{{#> layout }}
  My Content
{{/layout}}
    

Site Content
{{> @partial-block }}
    

Partials - Inline


{{#*inline "myPartial"}}
  My Content
{{/inline}}

{{#each children}}
  {{> myPartial}}
{{/each}}
    

Custom Helpers

Custom Helpers


Handlebars.registerHelper(
  'fullName',
  (person) =>
    `${person.firstName} ${person.lastName}`,
);
    

Custom Helpers


<div class="post">
  <h1>By {{fullName author}}</h1>
  <div class="body">{{body}}</div>

  <h1>Comments</h1>

  {{#each comments}}
    <h2>By {{fullName author}}</h2>
    <div class="body">{{body}}</div>
  {{/each}}
</div>
    

Custom Helpers - Block


Handlebars.registerHelper('bold', function(options) {
  return new Handlebars.SafeString(
    '<div class="mybold";>'
    + options.fn(this)
    + '</div;>');
});
    

Custom Helpers - Block


<div class="entry">
  <h1>{{title}}</h1>
  <div class="body">
    {{#bold}}{{body}}{{/bold}}
  </div>
</div>
    

Express Integration

Express Integration


npm install hbs
    

Express Integration


app.set('view engine', 'hbs');

...

res.render('not-found', { title: '404 Not Found' });
    

IRL

IRL - Comparators


Handlebars.registerHelper('eq', function (a, b) {
  return a === b;
});

Handlebars.registerHelper('gt', function (a, b) {
  return a > b;
});

...
    

IRL - Comparators


{{#if (eq value1 value2)}}
  // true
{{else}}
  // false
{{/if}}
    

IRL - Logical


Handlebars.registerHelper('and', function () {
  const operands = Array.prototype.slice.call(
    arguments,
    0,
    arguments.length - 1
  );

  return operands.reduce((r, x) => r && x, true);
});
    

IRL - Complex Filters


{{set 'video' (
  $findby property.files (
    $defer @helpers.$fieldMatches 'url' (
      $defer
        @helpers.$stringIncludes
          'https://youtu.be'
          'https://www.youtube.com'
    )
  )
)}}