Template.subscriptionsReady 禁用 onRendered 功能
Template.subscriptionsReady disables onRendered functionality
我正在 Template.templatename.OnRendered 中初始化日期选择器和表单验证。
$('#dateAccepted').datepicker({
endDate: new Date(),
todayBtn: true,
todayHighlight: true,
autoclose: true
});
我正在 Template.templatename.onCreated 中进行订阅、collection 查询等。
Template.insertContract.onCreated(function () {
var self = this;
self.autorun(function() {
self.subscribe('getContracts');
self.subscribe('getSuppliers' ,function(){
var suppliers = Supplier.find({}).fetch();
var sOptions = createOptions('supplier','supplierName',suppliers, true);
Session.set('supplierOptions', sOptions);
});
self.subscribe('getItems');
});
});
如果我将 Template.subscriptionsReady 放在我的模板上,日期选择器和表单验证将停止工作。没有错误消息。
这个问题被问了很多,但诚然很难搜索到。 是关于渲染轮播项目的类似问题。
这是正在发生的事情:
- 您的模板呈现并
onRendered
被调用。
- 您的订阅尚未准备就绪,因此未呈现日期选择器,但 (1) 中的初始化代码 运行s 就像它已经呈现一样。
- 最终呈现日期选择器。
一个可能的答案是在 sub-template 中呈现日期选择器。在 sub-template 的 onRendered
中你可以 运行 初始化代码,因为你可以保证它在 DOM 中。有关示例,请参阅上述问题的答案。
David 描述的很准确,sub-template 方法在某些情况下是一个不错的选择(我自己已经做过很多次)。
但有时感觉没有必要创建 sub-template,尤其是当它包含所有(或大部分)原始模板时。在这种情况下,您可以将订阅逻辑移至 onRendered 回调并使用 ReactiveVar 触发模板渲染。
这是一个例子:
Template.showStuff.onRendered(function() {
this.isReady = new ReactiveVar(false);
this.subscribe('mySubscription', () => {
this.isReady.set(true);
Tracker.afterFlush(() => {
this.$('#dateAccepted').datepicker({
endDate: new Date(),
todayBtn: true,
todayHighlight: true,
autoclose: true
});
});
});
});
然后定义一个助手以在模板中使用。
Template.showStuff.helpers({
isReady: function() {
return Template.instance().isReady.get();
};
});
并使用上述帮助程序将依赖于订阅的内容包装到您的模板中。
<template name="showStuff">
{{#if isReady}}
...datepicker and form stuff
{{/if}}
</template>
请注意,您必须将日期选择器初始化内容放在 Tracker.afterFlush 中,因为只有在下一个刷新周期之后 DOM 才会真正呈现。如果您没有嵌入 afterFlush,那么将执行日期选择器初始化,但不会有任何影响,因为日期选择器实际上尚未在 DOM.
中
当 sub-template 感到被迫时,我无数次使用了这个选项。
我正在 Template.templatename.OnRendered 中初始化日期选择器和表单验证。
$('#dateAccepted').datepicker({
endDate: new Date(),
todayBtn: true,
todayHighlight: true,
autoclose: true
});
我正在 Template.templatename.onCreated 中进行订阅、collection 查询等。
Template.insertContract.onCreated(function () {
var self = this;
self.autorun(function() {
self.subscribe('getContracts');
self.subscribe('getSuppliers' ,function(){
var suppliers = Supplier.find({}).fetch();
var sOptions = createOptions('supplier','supplierName',suppliers, true);
Session.set('supplierOptions', sOptions);
});
self.subscribe('getItems');
});
});
如果我将 Template.subscriptionsReady 放在我的模板上,日期选择器和表单验证将停止工作。没有错误消息。
这个问题被问了很多,但诚然很难搜索到。
这是正在发生的事情:
- 您的模板呈现并
onRendered
被调用。 - 您的订阅尚未准备就绪,因此未呈现日期选择器,但 (1) 中的初始化代码 运行s 就像它已经呈现一样。
- 最终呈现日期选择器。
一个可能的答案是在 sub-template 中呈现日期选择器。在 sub-template 的 onRendered
中你可以 运行 初始化代码,因为你可以保证它在 DOM 中。有关示例,请参阅上述问题的答案。
David 描述的很准确,sub-template 方法在某些情况下是一个不错的选择(我自己已经做过很多次)。
但有时感觉没有必要创建 sub-template,尤其是当它包含所有(或大部分)原始模板时。在这种情况下,您可以将订阅逻辑移至 onRendered 回调并使用 ReactiveVar 触发模板渲染。
这是一个例子:
Template.showStuff.onRendered(function() {
this.isReady = new ReactiveVar(false);
this.subscribe('mySubscription', () => {
this.isReady.set(true);
Tracker.afterFlush(() => {
this.$('#dateAccepted').datepicker({
endDate: new Date(),
todayBtn: true,
todayHighlight: true,
autoclose: true
});
});
});
});
然后定义一个助手以在模板中使用。
Template.showStuff.helpers({
isReady: function() {
return Template.instance().isReady.get();
};
});
并使用上述帮助程序将依赖于订阅的内容包装到您的模板中。
<template name="showStuff">
{{#if isReady}}
...datepicker and form stuff
{{/if}}
</template>
请注意,您必须将日期选择器初始化内容放在 Tracker.afterFlush 中,因为只有在下一个刷新周期之后 DOM 才会真正呈现。如果您没有嵌入 afterFlush,那么将执行日期选择器初始化,但不会有任何影响,因为日期选择器实际上尚未在 DOM.
中当 sub-template 感到被迫时,我无数次使用了这个选项。