Search code examples
javascriptmeteorflow-router

A good way to define default rendering templates in FlowRouter


When migrating to a new Meteor project which was replacing Iron-Router with Flow-Router, I really missed the functionality of Iron-Router to define default behaviours and settings that were usable globally.

I understand Flow-Router uses the "group" construct to be able to define default hook events which can be applied to any route attached to that group, but there seemed to be nothing available for defining default templates.

What is the best way to implement this type of default global or group template feature?


Solution

  • UPDATED BELOW:

    I have worked out what I think is a fairly effective and efficient way to do this.

    In reviewing the functionality of Flow-Router, I noticed that the router object includes a field which contains all group parameters, in FlowRouter.current().route.group.options

    This object contains any key-value pair defined in the group, regardless of whether they are used by the Flow-Router API or not.

    I then decided to use this as a simple way of passing some template defaults from the group to the router.

    First is the group definition:

    var mainRoutes = FlowRouter.group({
      name: "mainRoutes",
      defaultTemplates: {
        menu: "mainMenu",
        breadcrumb: "mainCrumb",
        sidebarLeft: "sidebarLeft",
        sidebarRight: "sidebarRight",
        footer: "mainFooter"
      }
    });
    

    Then in defining the route we can access these from this.group.options.defaultTemplates

    mainAppRoutes.route('/', {
      name: "home",
      action: function() {
        // Get the defaultTemplates object
        var templates = this.group.options.defaultTemplates;
        // Add route specific templates
        templates.content = "homeScreen";
        // Pass all the templates to the renderer
        BlazeLayout.render("appLayoutMain", templates);
      }
    });
    

    I like this pattern because it uses existing features of Flow-Router, and one extra line of code in the route, while allowing for defining of group wide default templates. This essentially mimics how Iron-Router was using template defaults in Router.config(), with the added benefit of local route template definitions not overwriting the whole default template object.

    • UPDATE The above has worked well for me, although I did end up having another problem which I had to solve to make it work consistently.

    Essentially, if you modify any underlying "route defaults" as we are doing, in the local route.action function, since Flow-Router is non-reactive, the router group object seems to persist from route to route as long as the routes are in the same group. Also this "options" object is passed to the router from the route definition. So what this means is that if you override a default parameter in the case above, it will be overwritten for all subsequent routes using that same group, after the route that overrides it is called.

    The solution I came up with was to do a defaults reset function as so: triggersExit: [ resetDefaults ] in the group definition.

    Then is just do a resetting of defaults. The reason I did it on exit is so that the next route being called can still override locally these defaults:

    function resetDefaults (context) {
      context.route.group.options.defaultLayoutTemplate = "mainAppLayout";
      context.route.group.options.defaultTemplates = {
        defaultTeamplates: "navMain",
        // ...
    };