Question

Ref to the question Trying to Migrate to Iron-Router from Router. I still dont understand how to migrate meteor router to iron-router. I am using router in my meteor project. The router file is like followings:

Meteor.Router.add({
  "/settings": function() {
    if (!Roles.userIsInRole(Meteor.user(), ['admin'])) {
      return false;
    }
    return 'site_settings';
  },
  "/new_page": function() {
    if (!Roles.userIsInRole(Meteor.user(), ['admin'])) {
      return false;
    }
    return 'new_page';
  },
  "/navigation": function() {
    if (!Roles.userIsInRole(Meteor.user(), ['admin'])) {
      return false;
    }
    return 'navigation';
  },
  "/login": function() {
    return 'loginButtonsFullPage';
  },

  "/users": function() {
    if (!Roles.userIsInRole(Meteor.user(), ['admin'])) {
      return false;
    }
    return 'admin_users';
    }
});

If someone knows how to use an iron-router to replace the return template in the right way. Much appreciate. I meet a little bit complicated router function, and I have no idea how to solve it. the code is like:

"/": function() {

    // Don't render until we have our data
    if (!GroundDB.ready()) {
    //if (!Offline.subscriptionLoaded('pages') || !Offline.subscriptionLoaded('settings')) {
      return 'loadingpage';
    } else {
      var page_slug = utils.getSetting('indexPage');
      var page = Pages.findOne({slug: page_slug});
      if(!page) {
        page = Pages.findOne();
        // if pages dont have any public pages
        if (!page) {
          var isIndexPageInNav=Navigation.findOne({"location":"header_active","pages.slug":page_slug});
          // if index page slug in navigation that means the user dont have right to view this slides or the index page not exist
          if(isIndexPageInNav)
          return 'loginButtonsFullPage';
          else
          return '404';

        }
        else {

          page_slug = page.slug;
        }
      }
      Session.set("page-slug", page_slug);

      return page.template;
    }
  }

As you know the iron-router need give a template at the begining. but with router I can return dynamic templates. How does iron-router implement this idea.

Was it helpful?

Solution

Router.map(function() {
  //site_settings being the name of the template
  this.route('site_settings', {
    path: '/settings',
    action: function() {
      if (!Roles.userIsInRole(Meteor.user(), ['admin'])) {
        //if the conditional fails render a access_denied template
        this.render('access_denied');
      } else {
        //else continue normally rendering, in this case the 'site_settings'
        //template
        this.render();
      }
    }
  });

  this.route('loginButtonsFullPage', {
    path: '/login'
  });
});

Note since you will be doing that if user is admin conditional a lot you can wrap that logic inside a controller and link it to all the relevant routes such as:

Router.map(function() {
  this.route('site_settings', {
    path: '/settings',
    controller: 'AdminController'
  });

  this.route('new_page', {
    path: '/new_page',
    controller: 'AdminController'
  });

  this.route('navigation', {
    path: '/navigation',
    controller: 'AdminController'
  });

  //etc...

  //don't need to add the controller for this one
  //since all users have access
  this.route('loginHuttonsFullPage', {
    path: '/login'
  });
});

AdminController = RouteController.extend({
  action: function() {
    if (!Roles.userIsInRole(Meteor.user(), ['admin'])) {
      this.render('access_denied');
    } else {
      this.render();
    }
  }
});

A couple of other things you will want to check out in iron-router are layouts with {{> yield}} and waitOn which is indispensable.

The docs at https://github.com/EventedMind/iron-router will do a better job of explaining those concepts then I can here.

Here is my attempt at your more complicated route. It may not work right away because I may be misunderstanding what you are doing but the key things are to substitute the returns with this.render(template_name); waitOn instead of checking if something is ready(), adding all the required subscriptions to the waitOn and then finally adding all your logic to an action

//note: index is the name of the route, you do not actually need a template called index.
//in the previous examples where no template to render was returned then iron-router will
//look for a template with the same name as the route but in this route we will be providing
//it with a specific route name in all cases
this.route('index', {
  path: '/',
  //assuming GroundDB is a subscription e.g. GroundDB = Meteor.subscribe('groundDB');
  //I don't know what your page and nav subscriptions are called but you should wait on them too.
  //if you haven't assigned them to a variable do something like 
  //pageSubscription = Meteor.subscribe('pages');
  waitOn: [GroundDB, pageSubscription, navigationSub],
  //the template to load while the subscriptions in waitOn aren't ready.
  //note: this can be defined globally if your loading template will be the same
  //for all pages
  loadingTemplate: 'loadingpage',
  //here we evaluate the logic on which page to load assuming everything has loaded
  action: function() {
    var page_slug = utils.getSetting('indexPage');
    var page = Pages.findOne({slug: page_slug});

    if (!page) {
      var isIndexPageInNav = Navigation.findOne({"location":"header_active","pages.slug":page_slug});
      if(isIndexPageInNav)
        this.render('loginButtonsFullPage');
      else
        this.render('404');
    } else {
      page_slug = page.slug;
    }

    Session.set("page-slug", page_slug);
    this.render(page.template);
  }

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