44

テンプレートコンテキストの状況に遭遇し、回避策を見つけるのに苦労しています。


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

{{#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
        }
    ]
}


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

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

ハンドルバーパスを使用して親コンテキストに戻ることでこれをある程度回避できますが、これはテンプレートヘルパーのコンテキストには影響しないため、inはcurrentまたは、ではなくcurrentを参照し、私たちが現在繰り返しているものを知っています。../optionsthisTemplate.vote.is_selected_optionparticipantvoteoptionoption

DOM操作やjQueryシェナニガンに頼らずに、これを回避する方法について何か提案はありますか?

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

4

9 に答える 9

84

Spacebars (Meteorの新しいテンプレートエンジン){{#each}}以降、を使用してブロック内の親コンテキストにアクセスできるようです../

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

于 2014-01-11T19:46:06.370 に答える
5

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

<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レベルではなく、ヘルパーレベルでデータを拡張します。これは、少し軽量だと思います。

気になる場合は、eachWithParentこの機能を抽象化するハンドルバーブロックヘルパーを作成してみてください。ハンドルバーに対するMeteorの拡張機能は、https ://github.com/meteor/meteor/wiki/Handlebarsに記載されています。

于 2012-12-13T01:51:25.837 に答える
2

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

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

ヘルパーやイベントなどでこのparent_idを使用して、findOneを使用して親に戻ります。これは明らかに最適とは言えないことですが、親コンテキストを参照する方法がない限り、これが私の頭に浮かぶ最も簡単な方法です。方法はあるかもしれませんが、ドキュメントに記載されていない場合は、Meteorの内部動作に非常によく隠されています。見つかった場合は、この質問を更新してください。

于 2012-12-10T06:51:25.017 に答える
2

ロングショットですが、おそらくこれでうまくいく可能性があります。

{{#with ../}}
  {{#each options}}
    {{this}}
  {{/each}}
{{/with}}
于 2012-12-18T09:31:03.500 に答える
2

これは人生を楽にするはずです。

// 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);
});

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

于 2013-12-13T00:35:24.323 に答える
2

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

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);
});
于 2015-09-26T20:04:14.140 に答える
0

私は同様の方法で立ち往生し、他の回答で提案されている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')
于 2015-11-28T15:02:33.303 に答える
0

"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>

于 2016-04-20T10:30:26.090 に答える
0

{{#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です!

于 2017-03-12T15:44:21.400 に答える