我遇到了模板环境,我很难找到解决方法。
以下是相关模板:
{{#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_option
或participant
,并且无法知道我们当前的vote
迭代。
有关如何解决这个问题的任何建议,而不诉诸DOM操作和jQuery恶作剧?
这是一个模板问题,已经多次出现在我面前。我们需要一种在模板,模板帮助器和模板事件中达到模板上下文层次结构的正式方法。
答案 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)
"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;
答案 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,它是父母的身份!