3

Objective : I want to render one among template A or template B from my flow router function, based upon a document which is retrieved after a subscribe call.

More specifically, I want to render either an admin or a student template based upon the isAdmin field of a user document, retrieved after a completed subscribe call. My router function is as shown below.

FlowRouter.route('/songs/list', {
  name: 'Songs.list',
  subscriptions: function(params, queryParams) {
    this.register('getUser', Meteor.subscribe('allUsers', Meteor.userId()));
  }
  action(params, queryParams) {
    if(Meteor.user().isAdmin){
     BlazeLayout.render("admin_home");
    }
    else{
     BlazeLayout.render("student_home");
    }     
  }
});

The Flow router documentation mentions specifically that

FlowRouter only deals with registration of subscriptions. It does not wait until subscription becomes ready.

So there could be a case where the "if condition" is evaluated before the subscription has updated the local cache.

With iron-router, this is easily handled using a waitOn. However for flow router, I am forced to have 2 separate functions, which further enforces 2 separate url's, for rendering the admin and student templates.

Is this a design choice made by the flow router developers?

  • You should read [Migrating from Iron Router to FlowRouter (with Blaze)](https://www.okgrow.com/posts/flow-router-migration-guide) – Michel Floyd Jun 11 '16 at 19:37

3 Answers3

3

Why not carry subscription logic out of routing and use template level subscriptions with builtin Template.subscriptionsReady helper?

FlowRouter.route('/songs/list', {
    name: 'Songs.list',
    action: function(params) {
        BlazeLayout.render('home');
    }
});
<template name="home">
    {{#if Template.subscriptionsReady}}
        {{#if isAdmin}}
            {{> admin_home}}
        {{else}}
            {{> student_home}}
        {{/if}}
    {{/if}}
</template>
Template.home.onCreated(function() {
    this.subscribe('allUsers', Meteor.userId());
});

Template.home.helpers({
    isAdmin: function() {
        // check if user is admin
    }
});

This approach also recommended in FlowRouter docs.

Ramil Muratov
  • 548
  • 5
  • 13
1

Try: Meteor.subscribe('allUsers', { OnReady(){ if(Meteor.user().isAdmin){ BlazeLayout.render("admin_home"); } else{ BlazeLayout.render("student_home"); } }

Remownz
  • 417
  • 1
  • 4
  • 18
0

I think the function you're after is FlowRouter.subsReady, an example of how you might use it within a router (similar to IronRouter) is provided in the docs here.

So in your case, it might look something like:

FlowRouter.route('/songs/list', {
    name: 'Songs.list',
    subscriptions: function(params, queryParams) {
        this.register('getUser', Meteor.subscribe('allUsers', Meteor.userId()));
    },
    action(params, queryParams) {

        Tracker.autorun(function() {

            var ready = FlowRouter.subsReady("getUser");

            Tracker.nonreactive(function(){

                if(ready && Meteor.user().isAdmin){
                    BlazeLayout.render("admin_home");
                }
                else if(ready){
                    BlazeLayout.render("student_home");
                }
                else {
                    BlazeLayout.render("loading");
                }

            });
        });
    }
});
danwild
  • 1,886
  • 1
  • 26
  • 31