Question

I'm using iron-router in a meteor project. What I want to do is show my loadingTemplate only within a particular nested template on the page (i.e. the content area that uses the data my waitOn is waiting for), not in place of the whole page as happens with Router.onBeforeAction('loading');.

Is it possible to do this using iron-router?

My simplified code:

layout.html

<template name="layout">
    {{> yield}}
</template>

<template name="foo">
    //bunch of intro text
        {{> bar}}
    //a big CTA
</template>

<template name="bar">
    {{this.something}}
</template>

What I want to do is replace the bar template with the loadingTemplate until the data is loaded. The rest of the page can render. Here's the default way that, of course, shows loadingTemplate in place of the whole page (e.g. `foo'):

router.js

Router.configure({
  layoutTemplate: 'layout',
  notFoundTemplate: 'notFound',
  loadingTemplate: 'loading'
});

//Router.onBeforeAction('loading'); //Future SO visitors: use this to show the loading template on all routes, if that's what you desire. I only want to show the loading template on one route.

this.route('home', {
    path: '/',
    action: function () {
      if (this.ready()) // is there a short-hand version btw?
        this.render();
      else
        this.render('loading');
    },
    onBeforeAction: function () {
      //this.render('loading'); //shouldn't this be the short-hand version? Doesn't work.
    },
    waitOn: function() {
      return Meteor.subscribe('baz');
    },
    data: function () {
      return Baz.find();
    }
  });

If what I'm looking for isn't possible with iron-router, any suggested alternatives are most welcome. Thanks!

For future visitors, here are the iron-router docs.

Was it helpful?

Solution 2

Full credit to Geoffrey Booth for sending this in the right direction. The full technical answer to the original question follows. The short answer is yes, it IS possible to target specific nested templates using iron-router as Geoffrey mentioned. The more involved answer: there is likely a better alternative depending on your use case...see comments to Geoffrey's answer for a good discussion.

The full working code using the example in the original question:

The html

<template name="layout">
  {{> yield region='header'}}
  {{> yield region='body'}}
  {{> yield region='footer'}}
</template>

<template name="foo">
  //bunch of intro text
   {{> yield}}
  //a big CTA
</template>

<template name="bar">
  {{this.something}}
</template>

and the router

Router.onBeforeAction('loading');

Router.map(function () {
  this.route('home', {
    path: '/',
    template: 'bar',
    layoutTemplate: 'layout',
    loadingTemplate: 'loading',
    notFoundTemplate: 'notFound',
    yieldTemplates: {
      'myHeader': {to: 'header'},
      'myFooter': {to: 'footer'},
      'foo': {to: 'body'}
    },
    waitOn: function () {
      return Meteor.subscribe('baz');
    },
    data: function () {
      return Baz.find();
    }
  });
});

OTHER TIPS

Yes, it is possible. Read the section in the docs called Using a Layout with Yields. Basically what you need to do is add a few more yields to your layout template, and define other sub-templates to go into them. The 'loading' template will load only in the main yield.

<template name="layout">
  {{> yield region='header'}}
  {{> yield}}
  {{> yield region='footer'}}
</template>

and

Router.map(function () {
  this.route('home', {
    path: '/',
    template: 'foo',
    layoutTemplate: 'layout', // This and the following two can also be defined
    loadingTemplate: 'loading', // in Router.configure like your code does
    notFoundTemplate: 'notFound',
    yieldTemplates: {
      'myHeader': {to: 'header'}, // You need to define the other templates
      'myFooter': {to: 'footer'} // that will be sent into other yields
    },
    waitOn: function () {
      return Meteor.subscribe('baz');
    },
    data: function () {
      return Baz.find();
    }
  });
});

The action and onBeforeAction parameters in your code are unnecessary; that’s what waitOn is doing.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top