Template.subscriptionsReady禁用onRendered功能

时间:2016-01-13 21:41:16

标签: meteor meteor-blaze bootstrap-datepicker

我正在使用Template.templatename.OnRendered初始化datepickers和表单验证。

 $('#dateAccepted').datepicker({
    endDate: new Date(),
    todayBtn: true,
    todayHighlight: true,
    autoclose: true
});

我在Template.templatename.onCreated中进行订阅,收集查询等。

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放在我的模板上,则datepickers和表单验证将停止工作。没有错误消息。

2 个答案:

答案 0 :(得分:1)

这个问题被问了很多,但不可否认的是,搜索很难。 This是关于渲染轮播项目的类似问题。

以下是发生的事情:

  1. 您的模板呈现并调用onRendered
  2. 您的订阅尚未准备好,因此不会呈现日期选择器,但初始化代码会在(1)中运行,就好像它一样。
  3. 最终呈现日期选择器。
  4. 一个可能的答案是在子模板中呈现日期选择器。在子模板的onRendered中,您可以运行初始化代码,因为您可以保证它在DOM中。有关示例,请参阅上述问题的答案。

答案 1 :(得分:0)

在大多数情况下,大卫所描述的是现实,子模板方法是一个很好的选择(我自己已多次这样做了)。

但有时候只是觉得创建一个子模板是不必要的,特别是如果它包含原始模板的全部(或大部分)。在这种情况下,您只需将订阅逻辑移动到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,那么将执行datepicker初始化,但是没有任何影响,因为datepicker实际上还没有在DOM中。

当子模板感到被迫时,我已经无数次地使用了这个选项。