部分的なハンドルバーを介して変数を渡す


131

私は現在、express.jsアプリケーションでhandlebars.jsを扱っています。モジュール化を維持するために、すべてのテンプレートをパーシャルに分割しました。

私の問題:部分的な呼び出しで変数を渡す方法が見つかりませんでした。次のようなパーシャルがあるとしましょう:

<div id=myPartial>
    <h1>Headline<h1>
    <p>Lorem ipsum</p>
</div>

このパーシャルを「myPartial」という名前で登録したとしましょう。別のテンプレートでは、次のように言うことができます:

<section>
    {{> myPartial}}
</section>

これは正常に機能し、パーシャルは期待どおりにレンダリングされ、私は幸せな開発者です。しかし、今必要なのは、この呼び出しを通じてさまざまな変数を渡し、たとえば、見出しが指定されているかどうかをパーシャル内でチェックする方法です。何かのようなもの:

<div id=myPartial>
    {{#if headline}}
    <h1>{{headline}}</h1>
    {{/if}}
    <p>Lorem Ipsum</p>
</div>

そして、呼び出しは次のようになります。

<section>
    {{> myPartial|'headline':'Headline'}}
</section>

とか、ぐらい。

テンプレートをレンダリングする前に、必要なすべてのデータを定義できることはわかっています。しかし、私は説明したようにそれを行う方法が必要です。可能な方法はありますか?

回答:


214

ハンドルバーのパーシャルは、パーシャルのコンテキストとなる2番目のパラメーターを取ります。

{{> person this}}

バージョンv2.0.0 alpha以降では、名前付きパラメーターのハッシュを渡すこともできます。

{{> person headline='Headline'}}

これらのシナリオのテストを確認できます 。 blob / e290ec24f131f89ddf2c6aeb707a4884d41c3c6d / spec / partials.js#L26-L32


5
これがあなたのシナリオにどのように当てはまるかはすぐにはわかりませんか?ソリューションを書いてもらえますか-ケースに適用してください。ありがとう!
serverman、2013年

12
@Yehuda Katzを渡す代わりthisに、独自のコンテキストで渡すことができますか?たとえば、{new_variable: some_data}?のように、渡す追加のデータを定義します。
Tri Nguyen

22
「これ」を渡すことができるのは良いことですが、それだけでは十分ではありません。多くの場合、同じページで潜在的に特定のHTMLを再利用したいのですが、パーシャルにIDがあると失敗します...同じIDが複数回表示されて無効になります。パーシャルを呼び出すときに引数を渡して、その内容をさらにカスタマイズできると非常に便利です。
Xavier_Ex 2013

2
ハンドルバーのどのバージョンがこれをサポートしていますか?1.3.0を使用していますが、jsonを渡そうとするとコンパイルエラーが発生します{{> partialName {new_variable: some_data} }}
bafromca

1
@bafromcaは、任意のデータを渡すことはできず、単一のオブジェクトのみを渡すという正確な問題です。したがって、これを渡すか、json-dataをコントローラーまたはビューに返す新しいプロパティを作成します。2番目に、任意のデータをの形式でパーシャルに渡すことができるはずですkey=value。githubでこれをカバーする問題はありますか?
ohcibi 2014

18

念のため、部分的な引数を取得するためにここで実行したのは、一種のことです。パーシャル名とパーシャルに渡されるパラメーターのハッシュを取る小さなヘルパーを作成しました:

Handlebars.registerHelper('render', function(partialId, options) {
  var selector = 'script[type="text/x-handlebars-template"]#' + partialId,
      source = $(selector).html(),
      html = Handlebars.compile(source)(options.hash);

  return new Handlebars.SafeString(html);
});

ここで重要なことは、ハンドルバーヘルパーがRubyのような引数のハッシュを受け入れることです。ヘルパーコードでは、それらは関数の最後の引数の一部としてoptionshashメンバー内にあります。このようにして、最初の引数(部分的な名前)を受け取り、その後にデータを取得できます。

次に、Handlebars.SafeStringヘルパーからを返すか、「トリプルスタッシュ」を使用し{{{て、二重にエスケープしないようにします。

これが多かれ少なかれ完全な使用シナリオです:

<script id="text-field" type="text/x-handlebars-template">
  <label for="{{id}}">{{label}}</label>
  <input type="text" id="{{id}}"/>
</script>

<script id="checkbox-field" type="text/x-handlebars-template">
  <label for="{{id}}">{{label}}</label>
  <input type="checkbox" id="{{id}}"/>
</script>

<script id="form-template" type="text/x-handlebars-template">
  <form>
    <h1>{{title}}</h1>
    {{ render 'text-field' label="First name" id="author-first-name" }}
    {{ render 'text-field' label="Last name" id="author-last-name" }}
    {{ render 'text-field' label="Email" id="author-email" }}
    {{ render 'checkbox-field' label="Private?" id="private-question" }}
  </form>
</script>

これが…誰かに役立つことを願っています。:)


15

独自のヘルパーを作成する場合、これは非常に可能です。$このタイプの相互作用(およびその他)を実現するために、カスタムヘルパーを使用しています。

/*///////////////////////

Adds support for passing arguments to partials. Arguments are merged with 
the context for rendering only (non destructive). Use `:token` syntax to 
replace parts of the template path. Tokens are replace in order.

USAGE: {{$ 'path.to.partial' context=newContext foo='bar' }}
USAGE: {{$ 'path.:1.:2' replaceOne replaceTwo foo='bar' }}

///////////////////////////////*/

Handlebars.registerHelper('$', function(partial) {
    var values, opts, done, value, context;
    if (!partial) {
        console.error('No partial name given.');
    }
    values = Array.prototype.slice.call(arguments, 1);
    opts = values.pop();
    while (!done) {
        value = values.pop();
        if (value) {
            partial = partial.replace(/:[^\.]+/, value);
        }
        else {
            done = true;
        }
    }
    partial = Handlebars.partials[partial];
    if (!partial) {
        return '';
    }
    context = _.extend({}, opts.context||this, _.omit(opts, 'context', 'fn', 'inverse'));
    return new Handlebars.SafeString( partial(context) );
});

1
渡された引数にアクセスするには、それらを「ハッシュ」オブジェクトで検索する必要があります:{{hash.foo}}。(私はハンドルバーを使い始めたばかりで、これを理解するのに少し時間がかかりました)-ありがとう、素晴らしいヘルパー!
クラウディオブレッドフェルト2013

ヘルパーを使用する前に、パーシャルをプリコンパイルしておく必要があることに注意してください。私はnode.jsでハンドルバーを使用していますが、これが常に当てはまるとは限りませんでした(パーシャルはオンデマンドでコンパイルされました)。ロードされたパーシャルをプリコンパイルするための簡単なヘルパーを追加する必要がありましたが、これはうまくいきました!
Dan

@そのヘルパーを共有できる可能性はありますか?:)
Tom

1
@トム、ここにあります(うまくフォーマットする方法がわかりません、申し訳ありません): hbs.registerPartials(path.join(__dirname, '/views/partials'), function() { utils.precompileHandlebarsPartials(hbs); }); // Pre compile the partials precompileHandlebarsPartials : function(hbs) { var partials = hbs.handlebars.partials; for (var partial in partials) { if (typeof partials[partial] === 'string') { partials[partial] = hbs.handlebars.compile(partials[partial]); } }; }
Dan

@Danおそらくそれを独自の回答として追加する方が良いでしょう。
アレックス2014年


9

パーシャルで別のコンテキストを使用したいだけの場合、受け入れられた答えはうまく機能します。ただし、親コンテキストを参照することはできません。複数の引数を渡すには、独自のヘルパーを作成する必要があります。ハンドルバーのヘルパー2.0.0は次のとおりです(他の回答はバージョンで機能します<2.0.0)。

Handlebars.registerHelper('renderPartial', function(partialName, options) {
    if (!partialName) {
        console.error('No partial name given.');
        return '';
    }
    var partial = Handlebars.partials[partialName];
    if (!partial) {
        console.error('Couldnt find the compiled partial: ' + partialName);
        return '';
    }
    return new Handlebars.SafeString( partial(options.hash) );
});

次に、テンプレートで次のようなことができます:

{{renderPartial 'myPartialName' foo=this bar=../bar}}

そして、部分的には、次のようなコンテキストとしてこれらの値にアクセスできます。

<div id={{bar.id}}>{{foo}}</div>

私はハンドルバー1.0.0でこのバージョンを試しましたが、問題なく動作しました。
ChristopherLörken2015年

これは、「...」という名前の部分的な部分を「検索」するのですか
kemagezien

8

あなたはこのようなことをしたいように聞こえます:

{{> person {another: 'attribute'} }}

イェフダはすでにそれをする方法をあなたに与えました:

{{> person this}}

しかし明確にするために:

パーシャルに独自のデータを与えるには、次のように既存のモデル内に独自のモデルを与えるだけです。

{{> person this.childContext}}

言い換えると、これがテンプレートに与えるモデルの場合:

var model = {
    some : 'attribute'
}

次に、パーシャルに与える新しいオブジェクトを追加します。

var model = {
    some : 'attribute',
    childContext : {
        'another' : 'attribute' // this goes to the child partial
    }
}

childContextイェフダが言ったように部分のコンテキストになります-その中で、それはフィールドを見るだけですが、another見えません(またはフィールドを気にしませんsome)。あなたが持っていた場合はid、トップレベルのモデルでは、と繰り返しidchildContextに再び部分は内側のみ何見ていると、それだけで正常に動作しますchildContext



1

これが役立つかどうかはわかりませんが、インラインRadioButtonsパーシャルに渡される動的パラメーターと、コンテナー内のラジオボタンをレンダリングするクライアント(ブラウザー)を含むハンドルバーテンプレートの例を次に示します。

私が使用する場合は、サーバーのハンドルバーでレンダリングされ、クライアントが仕上げることができます。これにより、フォームツールは、ヘルパーなしでハンドルバー内にインラインデータを提供できます。

注:この例にはjQueryが必要です

{{#*inline "RadioButtons"}}
{{name}} Buttons<hr>
<div id="key-{{{name}}}"></div>
<script>
  {{{buttons}}}.map((o)=>{
    $("#key-{{name}}").append($(''
      +'<button class="checkbox">'
      +'<input name="{{{name}}}" type="radio" value="'+o.value+'" />'+o.text
      +'</button>'
    ));
  });
  // A little test script
  $("#key-{{{name}}} .checkbox").on("click",function(){
      alert($("input",this).val());
  });
</script>
{{/inline}}
{{>RadioButtons name="Radio" buttons='[
 {value:1,text:"One"},
 {value:2,text:"Two"}, 
 {value:3,text:"Three"}]' 
}}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.