访问Meteor模板和模板助手中的父上下文

时间:2012-12-09 17:09:16

标签: 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把手路径跳回到父上下文来解决这个问题,但这不会影响模板助手的上下文,所以{{ 1 {} {}}}引用当前的this,而不是当前的Template.vote.is_selected_optionparticipant,并且无法知道我们当前的vote迭代。

有关如何解决这个问题的任何建议,而不诉诸DOM操作和jQuery恶作剧?

这是一个模板问题,已经多次出现在我面前。我们需要一种在模板,模板帮助器和模板事件中达到模板上下文层次结构的正式方法。

9 个答案:

答案 0 :(得分:83)

Spacebars (Meteor's new template engine)开始,您可以使用{{#each}}访问../块中的父上下文。

在Meteor 0.9.1中,您还可以编写帮助程序并在其实现中使用Template.parentData()

答案 1 :(得分:4)

这不是特别漂亮,但我做过类似的事情:

<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建议的方法,但增加了辅助级别的数据而不是数据库级别,我认为这个数据更轻一些。

如果您喜欢,可以尝试编写一个抽取此功能的Handlebars块助手eachWithParent。 Meteor对车把的扩展记录在此处:https://github.com/meteor/meteor/wiki/Handlebars

答案 2 :(得分:2)

我不知道正式方式(如果有的话),但为了解决您的问题,我会将参与者与父ID进行链接,如下所示:

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

并在帮助器,事件等中使用此parent_id以使用findOne跳回到父级。 这显然是一个次优的事情,但只要无法引用父上下文,它就是我脑海中最简单的方法。 也许有一种方法,但它很好地隐藏在Meteor的内部工作中,而没有在文档中提及,如果是这样的话:如果你找到一个,请更新这个问题。

答案 3 :(得分:2)

这是一个很长的镜头,但也许这可行:

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

答案 4 :(得分: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);
});

这有效:)没有错误

答案 5 :(得分: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);
});

答案 6 :(得分: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')

答案 7 :(得分:0)

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

答案 8 :(得分: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,它是父母的身份!