Search code examples
javascriptmeteorroutesurl-routingiron-router

Meteor.js Iron Router and similar or dynamic routes


I am trying to build dynamic routes for an admin section on my site so that "/admin" would work as well as "/admin/users" and "/admin/users/add" and so on. I have tried some different combinations but still struggling with this. Below is what I've tried and in different orderes.

Ideally if I could just specify "/admin" but dynamically reference each new / as an argument that would be best for handling in the code. Example "/admin/1/2/3/4/5" and being able to reference the 1 2 3 etc. I didn't see anything like this in the docs though.

Router.route('/admin', {
    name: 'admin',
    path: '/admin',
    template: 'admin',
    layoutTemplate: 'layout_admin',
    action: function() {
        Session.set('apage', 'dashboard');
        Session.set('asect', null);
        this.render();
    }
});

// Not Working...
Router.route('/admin/:apage', {
    name: 'admin',
    path: '/admin/:apage',
    template: 'admin',
    layoutTemplate: 'layout_admin',
    action: function() {
        Session.set('apage', this.params.apage);
        Session.set('asect', null);
        this.render();
    }
});

// Not Working...
Router.route('/admin/:apage/:asect', {
    name: 'admin',
    path: '/admin/:apage',
    template: 'admin',
    layoutTemplate: 'layout_admin',
    action: function() {
        Session.set('apage', this.params.apage);
        Session.set('asect', this.params.asect);
        this.render();
    }
});

EDIT (Answered)

After some testing it seems calling a template should be (or easiest done) in the this.render() line and the routes should go from most restrictive/detailed to least - which I did try before. The problem seems to be using this.params on the template: line. This solution is not perfect but posting for anyone who may run into a similar problem. As far as further variables in the url like "/admin/1/2/3/4/5" it seems they would need additional routes and can't be fully dynamic as a "/" can not go into the params and the router would look for a route and return notFound unless you can an explicit matching route. There may be a work around that I did not find.

Working code below:

Router.route('adminPage', {
    path: '/admin/:asect/:apage',
    template: 'admin',
    layoutTemplate: 'layout_admin',
    action: function() {
        Session.set('asect', this.params.asect);
        Session.set('apage', this.params.apage);
        this.render('admin_' + this.params.asect + '_' + this.params.apage);
    }
});

Router.route('adminSect', {
    path: '/admin/:asect',
    template: 'admin',
    layoutTemplate: 'layout_admin',
    action: function() {
        Session.set('asect', this.params.asect);
        Session.set('apage', null);
        this.render('admin_' + this.params.asect);
    }
});

Router.route('admin', {
    path: '/admin',
    template: 'admin',
    layoutTemplate: 'layout_admin',
    action: function() {
        Session.set('asect', 'dashboard');
        Session.set('apage', null);
        this.render('admin_dashboard');
    }
});

Solution

  • There is a way to have optional parameters in routes (which is what you're looking for unless I'm mistaken). With that in mind, you should be able to manage using one router.

    Router.route('admin',{
        path: '/admin/:asect?/:apage?',
        template: 'admin',
        layoutTemplate: 'layout_admin',
        action: function() {
    
            var asect  = this.params.asect || 'dashboard',
                apage  = this.params.apage || null,
                render = (function(){
                    if(apage !== null) {
                        return 'admin_'+ asect +'_'+ apage;
                    } else {
                        return 'admin_'+ asect;
                    }
                })();
    
            Session.set('asect', asect);
            Session.set('apage', apage);
            this.render(render);
        }
    });
    

    The ? after each parameter in the path designates it as an optional parameter. You should be able to then check if it has been defined or otherwise assign a default value and then structure your view and session accordingly.

    Note: You can test in this MeteorPad - just update the URL according to the names of the example templates.

    http://meteorpad.com/pad/Ri4Np5xDJXyjiQ4fG