web-dev-qa-db-ja.com

Meteorテンプレートおよびテンプレートヘルパーの親コンテキストへのアクセス

テンプレートコンテキストの状況に陥り、その方法を見つけるのに苦労しています。


問題のテンプレートは次のとおりです

{{#each votes}}
    <h3>{{question}}</h3>

    <ul>
        {{#each participants}}
            <li>
                <p>{{email}}</p>
                <select name="option-select">
                    {{#each ../options}}
                    <option value="{{option}}" class="{{is_selected_option}}">{{option}}</option>
                    {{/each}}
                </select>
            </li>
        {{/each}}
    </ul>
</div>
{{/each}}


そして、ここに投票文書の例があります:

{
    _id: '32093ufsdj90j234',
    question: 'What is the best food of all time?'
    options: [
        'Pizza',
        'Tacos',
        'Salad',
        'Thai'
    ],
    participants: [
        {
            id: '2f537a74-3ce0-47b3-80fc-97a4189b2c15'
            vote: 0
        },
        {
            id: '8bffafa7-8736-4c4b-968e-82900b82c266'
            vote: 1
        }
    ]
}


そして、ここに問題があります...

テンプレートが参加者の#eachにドロップすると、voteコンテキストにアクセスできなくなるため、各投票で使用可能なオプションにアクセスできなくなります。

私はやや../options handlebarsパスを使用して親コンテキストに戻ることでこれを回避できますが、これはコンテキストに影響しませんテンプレートヘルパーのthis in Template.vote.is_selected_optionは、現在のparticipantまたはvoteではなく、現在のoptionを参照し、現在どのoptionを反復処理しているかを知る方法。

DOM操作やjQueryに頼らずにこれを回避する方法についての提案はありますか?

これはテンプレートの問題で、私にとっては何度も出てきました。テンプレート、テンプレートヘルパー、およびテンプレートイベントで、テンプレートコンテキスト階層に到達する正式な方法が必要です。

44
cmal

特にきれいではありませんが、私はこのようなことをしました:

<template name='forLoop'>
{{#each augmentedParticipants}}
{{> participant }}
{{/each}}
</template>

<template name='participant'>
...
Question: {{this.parent.question}}
...
</template>


// and in the js:
Template.forLoop.helpers({
    augmentedParticipants: function() {
        var self = this;
        return _.map(self.participants,function(p) {
            p.parent = self;
            return p;
        });
    }
});

これはAVGPが提案したアプローチに似ていますが、dbレベルではなくヘルパーレベルでデータを拡張します。

気に入れば、この機能を抽象化するHandlebarsブロックヘルパーeachWithParentを記述してみてください。 Meteorのハンドルバーへの拡張機能はここに文書化されています: https://github.com/meteor/meteor/wiki/Handlebars

5
zorlak

スペースバー(流星の新しいテンプレートエンジン) なので、_{{#each}}_を使用して_../_ブロック内の親コンテキストにアクセスできます。

Meteor 0.9.1では、ヘルパーを記述し、その実装で Template.parentData() を使用することもできます。

83
opyh

これにより、生活が楽になります。

// use #eachWithParent instead of #each and the parent._id will be passed into the context as parent.
Handlebars.registerHelper('eachWithParent', function(context, options) {

    var self = this;
    var contextWithParent = _.map(context,function(p) {
        p.parent = self._id;
        return p;
    });

    var ret = "";

    for(var i=0, j=contextWithParent.length; i<j; i++) {
        ret = ret + options.fn( contextWithParent[i] );
    }
    return ret;
});

先に行くと変更

p.parent = self._id;

親コンテキストでアクセスしたいものに。

修正済み:

// https://github.com/meteor/handlebars.js/blob/master/lib/handlebars/base.js

// use #eachWithParent instead of #each and the parent._id will be passed into the context as parent.
Handlebars.registerHelper('eachWithParent', function(context, options) {
    var self = this;
    var contextWithParent = _.map(context,function(p) {
        p.parent = self._id;
        return p;
    });

    return Handlebars._default_helpers.each(contextWithParent, options);
});

これは動作します:)エラーなし

2
Chet

それは長いショットですが、おそらくこれはうまくいくかもしれません:

{{#with ../}}
  {{#each options}}
    {{this}}
  {{/each}}
{{/with}}
2
danielsvane

グローバルテンプレートヘルパーを登録するだけです:

Template.registerHelper('parentData',
    function () {
        return Template.parentData(1);
    }
);

hTMLテンプレートで次のように使用します。

{{#each someRecords}}
  {{parentData.someValue}}
{{/each}}

=======編集

Meteor 1.2+の場合、以下を使用する必要があります。

UI.registerHelper('parentData', function() {
  return Template.parentData(1);
});
2
Jan Curn

正式な方法(ある場合)はわかりませんが、問題を解決するために、次のように参加者を親IDにリンクします。

{
    _id: "1234",
    question: "Whats up?",
    ...
    participants: [
      {
        _id: "abcd",
        parent_id: "1234",
        vote: 0
      }
    ]
}

そして、このparent_idをヘルパー、イベントなどで使用して、findOneを使用して親に戻ります。これは明らかに最適ではありませんが、親コンテキストを参照する方法がない限り、最も簡単な方法です。方法はあるかもしれませんが、ドキュメントに記載されていない場合は、Meteorの内部の動作に非常によく隠されています。

2
geekonaut

私は同様の方法で立ち往生し、他の回答で提案されているTemplate.parentData()アプローチが現在イベントハンドラー内で機能しないことがわかりました( https://github.com/meteor/meteor/issues/5491を参照) )。ユーザーLirbankは、この簡単な回避策を投稿しました。

同じテンプレートで、外側のコンテキストから内側のコンテキストのhtml要素にデータを渡します。

{{#each companies}}
  {{#each employees}}
    <a href="" companyId="{{../id}}">Do something</a>
  {{/each}}
{{/each}}

これで、次のようなイベントハンドラーから会社IDにアクセスできます。

$(event.currentTarget).attr('companyId')
0
oskare
"click .selected":function(e){
    var parent_id = $(e.currentTarget).parent().attr("uid");
    return parent_id
  },
<td id="" class="staff_docs" uid="{{_id}}">
                                        {{#each all_req_doc}}
                                                <div class="icheckbox selected "></div>
  {{/each}}
  </td>
0
BGbhavesh

{{#each parent}}

{{#each child}}

<input type="hidden" name="child_id" value="{{_id}}" />

<input type="hidden" name="parent_id" value="{{../_id}}" />

{{/each}}

{{/each}}

_idは事の_didではなく、親のidです!

0
Andy