Using route-queries to set data context in route


#1

I have the following route setup:

Router.route('/:showSlug/:episodeSlug', {
	name: 'episode',
  controller: 'ApplicationController',
  loadingTemplate: 'loading',

	waitOn: function() {
    return [
      subs.subscribe('allUsers'),
      subs.subscribe('episodeBySlug', this.params.episodeSlug)
    ];
  },

	onBeforeAction: function() {
    var show = Shows.findOne({slug: this.params.showSlug});
    var episode = Episodes.findOne({slug: this.params.episodeSlug});

    if(!show || !episode) {
      Router.go('index');
    } else {
      this.next();
    }
	},

  action: function() {
    if(this.params.query.topic) {
      var topicId = this.params.query.topic;
      var topic = Topics.findOne(topicId);

      // Render Topic
      if(topic) {
        this.render('topic', {
          to: 'topic',
          waitOn: function() {
            return subs.subscribe('topicById', topicId);
          },
          data: function() {
            return Topics.findOne(topicId);
          },
        });
      }
      else {
        // Clear Query
        Router.query.clear();
      }
    }

    // Render Episode to Main Yield
    this.render('episode');
  },

  data: function() {
    return Episodes.findOne({slug: this.params.episodeSlug});
  }
});

And I’m changing the route query topic=_id with:

var query = 'topic=' + this._id;

Router.go(Router.current().route.getName(), Router.current().params, {
      query: query
    });

Basically what I want is for the data context of topic to change when the query parameter is changed, eg.:

http://localhost:3000/firstdayback/your-stories?topic=aT6curC3TXTbAKxSp

But when I’m changing the query parameter (on the live production server) it’s super slow, takes up to a couple of seconds even before the query is added to the url. I know several things can cause this, so I’ve tried stripping down everything; removing the loading of the topic template, subscriptions etc. but somehow changing the route parameter still seems to be really slow.

What I’m assuming is that with Router.go() I’m actually re-rendering the episode template (which I don’t want) for every change, and that’s whats causing the delay before the query gets added to the route. What am I doing wrong here?


#2

I basically want to do this:

Router.route('/:showSlug/:episodeSlug', {
	name: 'episode',
  controller: 'ApplicationController',

	onBeforeAction: function() {
    var show = Shows.findOne({slug: this.params.showSlug});
    var episode = Episodes.findOne({slug: this.params.episodeSlug});

    if(!show || !episode) {
      Router.go('index');
    } else {
      this.next();
    }
	},

  action: function() {

    // Render Topic to Topic Yield
    if(this.params.query.topic) {
      var topicId = this.params.query.topic;
      var topic = Topics.findOne(topicId);

      if(topic) {
        this.render('topic', {
          to: 'topic',
          loadingTemplate: 'loading',
          waitOn: function() {
            return subs.subscribe('topicById', topicId);
          },
          data: function() {
            return Topics.findOne(topicId);
          },
        });
      }
      else {
        // Clear Query
        Router.query.clear();
      }
    }

    // Render Episode to Main Yield
    this.render('episode', {
      loadingTemplate: 'loading',
      waitOn: function() {
        return [
          subs.subscribe('allUsers'),
          subs.subscribe('episodeBySlug', this.params.episodeSlug)
        ];
      },
      data: function() {
        return Episodes.findOne({slug: this.params.episodeSlug});
      }
    });
  }
});

So that each individual template on that route has a different waitOn / subscription so that I can control loading per yield. But this doesn’t work, don’t know if you can set waitOn with this.render?


#3

Something I actually understand…

this.render('...', function () {
            return {
                data: function () {
                    Meteor.call(...);
                    return {...}
                    };
                },
                waitOn: function () {
                    return Meteor.subscribe('...', this.params.id);
                }
            }
        });

#4

I ended up doing this:

Router.route('/:showSlug/:episodeSlug', {
	name: 'episode',
  controller: 'ApplicationController',

  waitOn: function() {
    return [
      subs.subscribe('allUsers'),
      Meteor.subscribe('episodeBySlug', this.params.episodeSlug)
    ];
  },

	onBeforeAction: function() {
    var show = Shows.findOne({slug: this.params.showSlug});
    var episode = Episodes.findOne({slug: this.params.episodeSlug});

    if(!show || !episode) {
      Router.go('index');
    } else {
      this.next();
    }
	},

  action: function() {

    // Render Topic to Topic Yield
    if(this.params.query.topic) {
      var topicId = this.params.query.topic;
      var topic = Topics.findOne(topicId);

      // show id
      var show = Shows.findOne({slug: this.params.showSlug});

      if(topic) {
        this.render('topic', {
          data: function() {
            return {
              topic: Topics.findOne(topicId),
              showId: show._id
            };
          },
          to: 'topic'
        });
      }
      else {
        // Clear Query
        Router.query.clear();
      }
    }

      // Render Episode to Main Yield
      this.render('episode', {
        data: function() {
          return Episodes.findOne({slug: this.params.episodeSlug});
        }
      });
  }
});

The performance issues was not related to the yields or routes and had something to do with subscriptions and template helpers. Just thought I’d post a solution for my own problem here for reference.