How to change layoutTemplate depending on some expression? Iron-router
Asked Answered
P

4

5

My app have multiple layouts for different needs, and I want to choose it dynamically. For example depending of GET params, or if user logged in.

How can i do this?

Presumptuous answered 26/2, 2014 at 9:18 Comment(3)
Personally, I would move this bit of logic to the template (using {{#if cond}} ... {{else}} ... {{/if}} and communicate the condition using the data available in iron-router. Is there any reason, apart from keeping templates completely logic-less, that you are not taking this approach?Bangalore
Are you already using Iron Router or any other router package?Whaler
Based on this issue, it looks like dynamically configuring the layoutTemplate doesn't currently work. I tried several permutations of conditionally assigning the template in the before hook in both Router.configure and in a specific route. None of those experiments worked.Excursus
D
4

EDIT Since the author edited the question here, and also the specs of iron:router has changed over time, I decided to refresh this answer a little to prevent confusion.

The documentation on using iron:router package can be found here.

There are a few possible answers to the question depending on what type of the "parameters".

Typically the main source of knowledge will be the path, because the user does not necessarily expect the page layout to be changed if the path remains the same. In this case the thing is pretty simple, because the only thing you need is to define appropriate routes:

Router.route('/some/path/', {
  layoutTemplate: 'myFirstLayoutTemplate'
});

Router.route('/another/path/', {
  layoutTemplate: 'mySecondLayoutTemplate'
});

If you ever need more refined control you can always choose the layout manually in the action hook assigned to the give route:

Router.route('/some/path', {
  /* ... */
  action: function () {
    if (Meteor.user()) { // check if user is logged in
      this.layout('loggedInUserLayout');
    } else {
      this.layout('someDefaultLayout');
    }
    // you need this because otherwise the router
    // will not render your templates
    this.render();
  }
});

Please note that the action hook is run within a computation and since Meteor.user() is a reactive data source your page will be re-rendered every time the user logs-in / logs-out.

More details about layouts can be found here.

Disordered answered 26/2, 2014 at 16:28 Comment(1)
Thank you! For those who want to avoid using this, this also works: Router.current().layout('loggedInUserLayout'). Helpful for those using arrow functions for example.Apiarist
T
4

You can actually change the layoutTemplate dynamically using this.router.layout() from within the before hook(and possibly other hooks). It's a bit hidden, and likely to change but here is how I was able to change the layoutTemplate depending on whether a user is logged in or not:

Router.configure({
    layoutTemplate: "defaultLayout",
    before: function (pause) {
        if(!Meteor.user()) {
            // render the login template but keep the url in the browser the same
            this.router.layout("loginLayout");
            this.render('login');

            // pause the rest of the before hooks and the action function
            pause();
        }else{
            //Here we have to change the layoutTemplate back to the default
            this.router.layout("defaultLayout");
        }
    }
});

This might get a bit complicated if you have multiple layoutTemplates since once the route is no longer paused it will retain the new layoutTemplate that you have set unless you change it again.

Traveler answered 18/4, 2014 at 7:52 Comment(1)
Just a note to patrons; as of recent, iron:router has replaced pause() with this.next(), so this code will not work without modification: #26630335Weaponeer
W
0

Meteor currently does not have the ability to render templates dynamically on the server before serving them to the client. Instead it serves the whole complete bundle together.

So within that bundle, you create templates and use them depending on user actions, url paths, session parameters etc.

Take a look at Iron Router which will get you going.

There is also an ongoing discussion on the meteor-talk google group and an item on meteor roadmap trello board.

Whaler answered 26/2, 2014 at 16:9 Comment(0)
A
0

I'll just leave this here, it's from 2019 and works after some difficulties...

Router.route('/', function () {

    Router.current().layout("applicationLayoutEmpty");
    this.render('landing', {to: 'content'});

    if(Meteor.userId()){
        Router.go("/social");
    }

});

The magic is in: Router.current().layout("applicationLayoutEmpty");

It uses the default set in main.js when you're configuring IronRouter, but this can be used even in your browser window -- go try it!

Aeromarine answered 2/3, 2019 at 5:18 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.