0

I want to decide based on a boolean attribute in a document (mode), which subscriptions the user gets, but I have problems with the design approach. If I use this.data() and a if clause in the waitOn function, I will get the 404 page rendered, because I need first the subscription.

Here is my code:

this.route('gamePage', {
        path: '/game/:slug/viewGame/:produceDate?/:releaseDate?',
        onBeforeAction: [memberFilter],
        waitOn: function() {
            var game = this.data();
            if (game.mode) {
                if (this.params.produceDate && this.params.releaseDate) {
                    return [Meteor.subscribe('singleGame', this.params.slug),
                        Meteor.subscribe('authorsMode', this.params.slug, this.params.produceDate, this.params.releaseDate)];
                } else {
                    return [Meteor.subscribe('singleGame', this.params.slug), Meteor.subscribe('console', this.params.slug)];
                }
            } else {
                return [Meteor.subscribe('singleGame', this.params.slug),
                    Meteor.subscribe('authors', this.params.slug)];

            }
        },
        data: function() {
            return Games.findOne({slug: this.params.slug});
        }

Any help would be greatly appreciated.

user3475602
  • 1,167
  • 2
  • 18
  • 41

1 Answers1

1

To achieve that directly you would need Iron Router to let you have 2 levels of subscriptions, the first one making data available to the next level of subscription. This feature doesn't exist right now. I've just submitted an issue to IR repo asking for this feature.

The workaround for this is having different URL for each case, making intermediate redirections:

this.route('gamePage', {
  path: '/game/:slug/viewGame/:produceDate?/:releaseDate?',
  onBeforeAction: function() {
    var game = this.data();
    var params = {
      slug: this.params.slug,
      produceDate: this.params.produceDate,
      releaseDate: this.params.releaseDate
    }
    if (game.mode) {
      if (this.params.produceDate && this.params.releaseDate) {
        this.redirect('gamePageOption1', params);
      } else {
        this.redirect('gamePageOption2', params);
      }
    } else {
      this.redirect('gamePageOption3', params);
    }
  },
  waitOn: function() {
      return [Meteor.subscribe('games')];
  },
  data: function() {
      return Games.findOne({slug: this.params.slug});
  }
}

If you are using IR v < 0.9.3 be aware of an issue about intermediate redirections: ref1, ref2. If this is the case, you have to the redirection inside a Meteor.defer:

Meteor.defer(function() {
    this.redirect(...)
})
Tomas Romero
  • 7,746
  • 10
  • 45
  • 68
  • Thank you for your help! I am not a 100% sure if I understand your approach correctly. So, you suggest to have different routes like `this.route('gamePageOption1')`, `this.route('gamePageOption2')` with the same URL, but with different subscriptions? – user3475602 Sep 20 '14 at 17:38
  • Right, exactly that. One url could be `/game/:slug/viewGame/:produceDate?/:releaseDate?/withMode` an another `/game/:slug/viewGame/:produceDate?/:releaseDate?/noMode`, each with different subscriptions. – Tomas Romero Sep 20 '14 at 23:41
  • I just want to add, that I found an even better way (for my purpose). Instead of redirecting to different routes, I replaced the statement with `this.subscribe('collectionName', this.params.slug).wait();`. Worked for me! – user3475602 Sep 22 '14 at 16:30
  • That is actually a great solution! thanks for sharing. I suggest adding that comment as an answer and marking that as the accepted answer. – Tomas Romero Sep 22 '14 at 17:14