Открыть меню    

Handlebars-хелпер

Handlebars-хелпер

Handlebars-хелпер представляет собой простой идентификатор, за которым следуют ноль или более параметров (через пробел). Каждый параметр представляет собой handlebars-выражение. Параметром хелпера может также являться простая строка, число или логическое значение. Хелпер производит определенные операции с параметрами и возвращает HTML код.

Handlebars-хелперам также можно передать последовательность пар ключ-значение после всех непарных параметров. Ключи должны быть простыми идентификаторами, а значения — handlebars-выражениями (т.е. значения могут быть идентификаторами, путями, или строками).

jQuery or Javascript

{{link "Подробнее..." href=poem.url class="poem"}}

Блоковые хелперы

Блоковые хелперы позволяют определять пользовательские итераторы, а также другую функциональность, с помощью которой можно вызвать переданный блок в новом контексте. Блоковый хелпер записывается следующим образом:

jQuery or Javascript

{{#helper_name}}some_block{{/helper_name}}

При регистрации хелпера параметры в Handlebars.registerHelper передаются в том порядке, в котором они были переданы хелперу пользователем. Вслед за всеми указанными пользователем параметрами следует параметр options. Он имеет следующие свойства:

options.fn — содержит функцию, которая ведет себя как обычный скомпилированный шаблон Handlebars. В качестве параметра функция принимает контекст и возвращает строку.

Пример 1. Давайте определим блоковый хелпер, который изменяет разметку обернутого в него текста:

HTML

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

Регистрация:

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

Здесь в качестве параметра функции мы передали текущий контекст (this). Давайте укажем другой контекст, передав его хелперу как параметр:

Пример 2.

HTML

<div class="entry">
{{author}}
{{#with poem}}
  <div class="title">{{title}}</div>
  <div class="author">{{../author}}</div>
  <div class="year">{{year}}</div>
{{/with}}
</div>

Выполнить этот шаблон мы могли бы со следующим JSON, имеющим вложенные в объект poem ключи title и year:

jQuery or Javascript

{
  author: "Сергей Есенин",
  poem: {
    title: "Собаке Качалова",
    year: 1925
  }
}

Регистрация:

jQuery or Javascript

Handlebars.registerHelper('with', function(context, options) {
  console.log(context);   //{title: "Собаке Качалова", year: 1925}
  return options.fn(context);
});

Мы получим HTML-код:

HTML

<div class="entry">
  Сергей Есенин
  <div class="title">Собаке Качалова</div>
  <div class="author">Сергей Есенин</div>
  <div class="year">1925</div>
</div>

Обратим внимание, что в этом примере мы использовали сегмент ../ для указания пути к свойству author, находящемуся вне контекста poem.

Пример работы:

Handlebars.registerHelper('myHelper', function(conditional, options) {

    return options.fn(conditional); // conditional - это контекст

    console.log(conditional); // conditional    - { name : "Вася"}

});
var data = {
    flowers: [
        {
            name: "Daffodil",
            product: "daffodil",
            stock: "12",
            price: 1.99,
            obj: {
                name: "Вася"
            }
        }
    ]
};
{{#each flowers}}
<div class="dcell">

    {{#myHelper obj}}

        {{name}}

    {{/myHelper}}

</div>
{{/each}}

Но если элементов несколько код работать не будет. Исправим это:

{{#each flowers}}
<div class="dcell">

    {{#if obj}} // если obj не существует будет выведено "куку"

        {{#myHelper obj}}
            {{name}}
        {{/myHelper}}

    {{else}}

    куку

    {{/if}}

    <img src="{{product}}.png"/>
    <label for="{{product}}">{{name}}:</label>
    <input name="{{product}}" data-price="{{price}}" data-stock="{{stock}}"
        value="{{#gt stock 0}}1{{else}}0{{/gt}}" required />
</div>
{{/each}}

Немного усложним ситуацию и выведем надпись лищь для тех элементов у которых есть свойство obj плюс у элемента название свойства продукт должно быть "aster"

Handlebars.registerHelper('myHelper', function(conditionalProduct, conditional, options) {

    if(conditionalProduct === "aster"){
        return options.fn(conditional);
    }
    else { //Handlebars возвращает блок, следующий за {{else}}, через функцию options.inverse:
        return options.inverse(conditional);
    }

});
<script id="flowerTmpl" type="text/x-handlebars-template">
    {{#each flowers}}
    <div class="dcell">

        {{#if  obj}}

            {{#myHelper product obj}}
                {{name}}
            {{else}}
                Здесь нет продекта с названием Aster

            {{/myHelper}}

        {{else}}

        куку

        {{/if}}

        <img src="{{product}}.png"/>
        <label for="{{product}}">{{name}}:</label>
        <input name="{{product}}" data-price="{{price}}" data-stock="{{stock}}"
            value="{{#gt stock 0}}1{{else}}0{{/gt}}" required />
    </div>
    {{/each}}
</script>
$(document).ready(function () {
    var data = {
        flowers: [
        { name: "Aster", product: "aster", stock: "10", price: 2.99,

            obj: {
                name: "Вася c Астером"
            }

        },
        { name: "Daffodil", product: "daffodil", stock: "12", price: 1.99,

            obj: {
                name: "Вася"
            }


         },
        { name: "Rose", product: "rose", stock: "2", price: 4.99 },
        { name: "Peony", product: "peony", stock: "0", price: 1.50 },
        { name: "Primula", product: "primula", stock: "1", price: 3.12 },
        { name: "Snowdrop", product: "snowdrop", stock: "15", price: 0.99 }
        ]
    };
    var tElem = $("#flowerTmpl");
    tElem.template({ flowers: data.flowers.slice(0, 3) }).appendTo("#row1");
    tElem.template({ flowers: data.flowers.slice(3) }).appendTo("#row2");
});

Комментарии к статье