1

I have the following template code:

<template name="dashboard">
  <div class="content-container-with-sidebar clearfix">
    <div class="dashboard-container">
    {{#if Template.subscriptionsReady}}
      <div id=masonry-grid class="masonry-grid clearfix">
        {{> timePieChartCard}}
        {{> expensePieChartCard}}
        {{> HighlightsCard}}
        {{> initializeMasonry}}
      </div>
    {{/if}}
    </div>
  </div>
</template>

I'd like to run the initializer for the masonry library after all the templates and their subscriptions/helpers load within the main dashboard template.

Each card has code similar to this:

<template name="HighlightsCard">
  {{#if highlightsExist}}
  <div class="col-md-6 masonry-grid-item">
    <div class="card highlights-card">
    </div>
  </div>
  {{/if}}
</template>

Template.highlightsCard.onCreated(function() {
  this.autorun(() => {
    this.subscribe('userOwnClientHighlightsData');
  });
});

Template.highlightsCard.helpers({
  highlights() {
    return Highlights.find({}, {
      limit: 4,
      sort: {createdAt: -1}
    }).fetch();
  },
  highlightsExist() {
    return (Highlights.find().count() > 0);
  }
});

I currently am setting a session that increases when each onRendered is run within the card templates, but once they all render their contents have still not loaded. I need the class masonry-grid-item to be visible in order for me to initialize masonry.

What's the best way to get a similar result as jquery's $(document).ready() ?

Update: each individual card in the dashboard template has it's own subscription to a different dataset.

2 Answers 2

2

Look at Tracker.afterFlush

Schedules a function to be called during the next flush

For example:

Template.dashboard.onRendered(()=>{
  Tracker.afterFlush(()=>{
    ...your code here
  });
});
Sign up to request clarification or add additional context in comments.

Comments

1

If I understand the problem correctly, you want to initialize your component after the subscription is complete and after all sub-templates (that also depend on the subscription data) are rendered.

Since I don't know what your JavaScript looks like, here is an example of what you can try.

Template.dashboard.onRendered(function() {
  this.isReady = new ReactiveVar(false);

  this.subscribe('subscriptionName', () => {
    this.isReady.set(true);
    Tracker.afterFlush(() => {
      // Initialize component here
    });
  });
});

Template.dashboard.helpers({
  isReady: () => {
    return Template.instance().isReady.get();
  },
});

And then use the isReady ReactiveVar in your template. In this case, isReadymay not be necessary (e.g. you could probably use the Template.subscriptionsReady helper), but I like to have explicit control of when to render incase my logic gets more complex in the future. Note, I removed {{> initializeMasonry}} because it looked like you were attempting to initialize your component via a helper.

<template name="dashboard">
  <div class="content-container-with-sidebar clearfix">
    <div class="dashboard-container">
    {{#if isReady}}
      <div id=masonry-grid class="masonry-grid clearfix">
        {{> timePieChartCard}}
        {{> expensePieChartCard}}
        {{> HighlightsCard}}
      </div>
    {{/if}}
    </div>
  </div>
</template>

The callback to Tracker.afterFlush will get executed on the next Blaze render cycle, which will be after your sub-templates are rendered.

1 Comment

I forgot to mention that each individual card has it's own subscription and helper to check if data is available. I've updated the original post above.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.