FlowRouter Documentation

repository·master·Indexed 22 days ago

https://github.com/kadirahq/flow-router

A lightweight, high-performance client-side router for Meteor applications. FlowRouter focuses on routing and URL management, decoupling these tasks from UI rendering and layout management. It features support for route grouping, triggers for entry and exit logic, reactive parameter retrieval via getParam and getQueryParam, and integration with Meteor subscriptions for fast-render support.

Tokens
3.7K
Snippets
19
Records
21
Agent score
27%

What's inside FlowRouter

  1. Understand FlowRouter's architectural philosophy

    master

    FlowRouter is a minimalistic router focused on UI performance. Unlike full-featured routers (like Iron Router), it follows these principles:

    • Decoupled Rendering: FlowRouter does not handle rendering. It expects you to use a rendering framework (like BlazeLayout for Blaze or meteor-react-layout for React) within the route's action.
    • Subscription Management: While you can register subscriptions at the router layer, it is highly recommended to handle subscriptions at the template/component layer. FlowRouter does not wait for subscriptions to complete before moving to the next route.
    • Client-Side Focus: FlowRouter is a client-side router and does not support server-side routing. For server-side routing in Meteor, use a dedicated solution like meteorhacks:picker.
    • No Data Context: FlowRouter does not provide a global data context to avoid the reactivity issues associated with Router.current().
  2. Use FlowRouter.getParam() instead of Router.current()

    master

    To avoid unpredictable re-renders and performance issues, do not use Router.current() to access route parameters inside reactive helpers or components. Router.current() triggers a re-run whenever any part of the URL changes (including query parameters or other route segments).

    Instead, use FlowRouter.getParam(paramName) to target a specific parameter. This ensures the helper only re-runs when that specific parameter actually changes.

    Templates['foo'].helpers({
        "someData": function() {
            // GOOD: Only re-runs if 'appId' changes
            var appId = FlowRouter.getParam('appId');
            return doSomething(appId);
        }
    });
  3. Group routes for organization and shared logic

    master

    You can use FlowRouter.group(options) to organize routes under a common prefix or name, and to apply shared logic like triggersEnter or triggersExit to all routes within that group. Groups can be nested.

    Common group options:

    • prefix: A string prefix applied to all routes in the group.
    • name: A name for the group.
    • triggersEnter: An array of functions to run when entering any route in the group.
    • triggersExit: An array of functions to run when exiting any route in the group.

    You can check the current group name using FlowRouter.current().route.group.name or the parent group name via FlowRouter.current().route.group.parent.name. Note that these properties are not reactive, but can be used with FlowRouter.watchPathChange() for reactivity.

    var adminRoutes = FlowRouter.group({
      prefix: '/admin',
      name: 'admin',
      triggersEnter: [function(context, redirect) {
        console.log('running group triggers');
      }]
    });
    
    // handling /admin/posts
    adminRoutes.route('/posts', {
      action: function() {
        // route logic
      }
    });
  4. Register and check subscriptions

    master

    FlowRouter allows you to register subscriptions directly within a route definition. This is useful for FastRender support. You can register global subscriptions that run on every route via FlowRouter.subscriptions. Use FlowRouter.subsReady(name) to reactively check if a specific subscription is ready, or use the callback version inside event handlers.

    // Registering in a route
    FlowRouter.route('/blog/:postId', {
        subscriptions: function(params) {
            this.register('myPost', Meteor.subscribe('blogPost', params.postId));
        }
    });
    
    // Checking status reactively
    Tracker.autorun(function() {
        if (FlowRouter.subsReady("myPost")) {
            // do something
        }
    });
    
    // Checking status in an event handler (callback version)
    Template.myTemplate.events({
       "click #id": function() {
          FlowRouter.subsReady("myPost", function() {
             // do something when ready
          });
       }
    });
  5. Manage layouts and rendering with FlowRouter

    master

    FlowRouter handles routing logic but does not handle UI rendering or layout management. To render components, you must use a layout manager (like BlazeLayout for Blaze or meteor-react-layout for React) inside the route's action method.

    FlowRouter.route('/blog/:postId', {
        action: function(params) {
            BlazeLayout.render("mainLayout", {area: "blog"});
        }
    });
  6. Migrate from FlowLayout to BlazeLayout

    master

    In version 2.0, FlowLayout has been renamed to BlazeLayout. To migrate:

    1. Remove meteorhacks:flow-layout.
    2. Add kadira:blaze-layout.
    3. Replace all calls to FlowLayout.render() with BlazeLayout.render().
    // Before
    FlowLayout.render('myTemplate');
    
    // After
    BlazeLayout.render('myTemplate');
  7. Migrate from meteorhacks:flow-router to kadira:flow-router

    master

    If you are upgrading to version 2.0 or later, you must switch to the new package name. Follow these steps:

    1. Remove the old package: meteor remove meteorhacks:flow-router
    2. Add the new package: meteor add kadira:flow-router
    meteor remove meteorhacks:flow-router
    meteor add kadira:flow-router
  8. Control FlowRouter initialization timing

    master

    If your application requires custom initialization before routing can begin, use FlowRouter.wait() to prevent automatic initialization in Meteor.startup(). Once your app is ready, call FlowRouter.initialize() manually.

    // app.js
    FlowRouter.wait();
    
    WhenEverYourAppIsReady(function() {
      FlowRouter.initialize();
    });
  9. Use Triggers to perform tasks on route entry and exit

    master

    Triggers allow you to execute code before entering a route (triggersEnter) or after exiting a route (triggersExit).

    Route-level Triggers

    Define triggersEnter and triggersExit arrays within the route options.

    Group-level Triggers

    Define triggersEnter and triggersExit within the FlowRouter.group() options to apply them to all routes in that group.

    Global Triggers

    Define triggers globally using FlowRouter.triggers.enter() and FlowRouter.triggers.exit(). You can filter which routes these apply to using the only or except options (you cannot use both simultaneously).

    Redirecting with Triggers

    Triggers provide a redirect function as the second argument. To redirect:

    • Call redirect(url).
    • It must be called within the same event loop cycle (no async, no Tracker.autorun).
    • It cannot be called multiple times.

    Stopping a route with the stop function

    In triggersEnter, you can use the third argument stop() to prevent the route's action from firing. This is useful for authentication or validation checks. When using stop(), you must still pass the redirect argument to the callback even if you don't use it.

    // Global triggers with filtering
    FlowRouter.triggers.enter([trackRouteEntry], {only: ["home"]});
    
    // Redirecting in a trigger
    FlowRouter.route('/', {
      triggersEnter: [function(context, redirect) {
        redirect('/some-other-path');
      }],
      action: function(_params) {
        // This will not be called if redirect is successful
      }
    });
    
    // Stopping a route execution
    function localeCheck(context, redirect, stop) {
      var locale = context.params.locale;
      if (locale !== 'fr') {
        stop();
      }
    }