Search code examples
meteoriron-router

MeteorJS one-page-app navigation


MeteorJS absolute noob here, so be gentle... :)

I am trying to build a one page web app, and I am using the iron:router.

The idea is that there are a few divs in the page, lets say 3, one for the menu, one which never changes and one where the content should change based on the menu selection.

In a regular page I would just load the content in that one div. But with meteor/router I figured I would use the layoutTemplate feature and put the common parts in one template, then call another one with {{> yield}}.

Problem 1: That worked fine when I only had the /room template, but as soon as I introduced the /user template, it just won't load :( It loads for a moment and then skips back to the /room, visibly reloads the /room. Now, ofcourse I'm doing something wrong, I just don't see what :(

Problem 2: It actually reloads the entire page whenever it loads /user and then goes back to /room, which means it disconnects and reconnects every time, is there a way to avoid that and to actually keep it as one page app that stays connected and only loads some template into a div?

router.js:

Router.configure({
    notFoundTemplate: "404"
});

Router.map(function () {
    this.route('/', {
        path: '/',
        layoutTemplate: 'welcome',
        onBeforeAction: function (pause) {
            if (checkLogin()) {
                Router.go('/room');
            } else {
                this.next();
            }
        }
    }),
    this.route('welcome', {
        path: '/welcome',
        layoutTemplate: 'welcome',
        onBeforeAction: function (pause) {
            if (checkLogin()) {
                Router.go('/room');
            } else {
                this.next();
            }
        }
    }),
    this.route('room', {
        path: '/room',
        layoutTemplate: 'base',
        onBeforeAction: baseAction
    }),
    this.route('user', {
        path: '/user',
        layoutTemplate: 'base',
        onBeforeAction: baseAction
    })
});

function baseAction(pause) {
    if (!checkLogin()) {
        Router.go('/welcome');
    } else {
        this.next();
    }
}

function checkLogin() {
    return Meteor.user() ? true : false;
}

base.js:

Template.base.events({
    "click #menu-logout": function () {
        Meteor.logout();
    },
    "click #menu-room": function () {
        window.location.href = '/room';
    },
    "click #menu-user": function () {
        window.location.href = '/user';
    }
});

base.html:

<template name="base">
    <div id="menu">
        <table style="height: 33px; width: 100%;">
            <tr>
                <td id="menu-room"><img src="img/logo.png" /></td>
                <td id="menu-user">me</td>
                <td id="menu-logout">logout</td>
            </tr>
        </table>
    </div>
    <div id="content">{{> yield}}</div>
    <div id="list">{{> tmpList}}</div>
</template>

room.html:

<template name="room">
    room data
</template>

user.html:

<template name="user">
    user data
</template>

Solution

  • Apparently, one should never give up :)

    The solution to both problems listed is to not use window.location for navigation but to use Router.go instead.

    This change in base.js fixed everything:

    Template.base.events({
        "click #menu-logout": function () {
            Meteor.logout();
        },
        "click #menu-room": function () {
            Router.go('/room');
        },
        "click #menu-user": function () {
            Router.go('/user');
        }
    });