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


这就是问题所在...

当模板进入#each参与者时,它不再有权访问vote上下文,因此无法访问每个投票的可用选项。

我可以通过使用把手路径跳回父上下文来解决这个问题../options,但这不会影响模板助手的上下文,所以thisinTemplate.vote.is_selected_option指的是 current participant,而不是 current voteor option,并且没有办法知道option我们当前正在迭代哪个。

关于如何解决这个问题的任何建议,而不诉诸 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 级别增加数据,我认为这有点轻量级。

如果你喜欢,你可以尝试编写一个 Handlebars 块帮助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

这应该让生活更轻松。

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

这是一个很长的镜头,但也许这可以工作:

{{#with ../}}
  {{#each options}}
    {{this}}
  {{/each}}
{{/with}}
于 2012-12-18T09:31:03.500 回答
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

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