问题
I am initializing datepickers and form validation in Template.templatename.OnRendered.
$('#dateAccepted').datepicker({
endDate: new Date(),
todayBtn: true,
todayHighlight: true,
autoclose: true
});
I am doing subscriptions, collection queries etc in 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');
});
});
If I put Template.subscriptionsReady on my template, datepickers and form validations stop working. No error messages.
回答1:
This question gets asked a lot, but admittedly it's hard to search for. This is a similiar question about rendering carousel items.
Here's what's happening:
- Your template renders and
onRendered
gets called. - Your subscription isn't ready yet, so the datepicker isn't rendered but the initialization code runs in (1) as if it had.
- Eventually the datepicker is rendered.
One possible answer is to render the datepicker in a sub-template. In the sub-template's onRendered
you can run the initialization code, as you can be guaranteed that it's in the DOM. See the answer to the aforementioned question for an example.
回答2:
What David described is spot on and the sub-template approach is a good option in several cases (I've done this many times myself).
But sometimes it just feels unnecessary to create a sub-template, especially if it would contain all (or the bulk of) your original template. In this situation you can just move your subscription logic to the onRendered callback and use a ReactiveVar to trigger the Template rendering.
Here is an example:
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
});
});
});
});
Then define a helper to use in the Template.
Template.showStuff.helpers({
isReady: function() {
return Template.instance().isReady.get();
};
});
And wrap the stuff in your Template that depends on the subscription using the above helper.
<template name="showStuff">
{{#if isReady}}
...datepicker and form stuff
{{/if}}
</template>
Note, you have to put your datepicker initialization stuff in a Tracker.afterFlush because it's only after the next flush cycle that the DOM is actually rendered. If you didn't embed in afterFlush, then the datepicker initialization would be executed but would have no affect because the datepicker is not yet actually in the DOM.
I've employed this option countless times when sub-templates just feels forced.
来源:https://stackoverflow.com/questions/34777586/template-subscriptionsready-disables-onrendered-functionality