Search code examples
javascriptcssmeteoriron-routermeteor-blaze

meteor js iron router: apply CSS change whenever route changes


I have homepage, contact page, and several other product related pages in my app.

The goal is to apply a background image to ONLY specifc routes: /homepage and /contact. If user navigates away from either route, apply some css change.

I am hacking this together now with a helper on my homepage, like so:

Template.homepage.rendered = function () {

    var route = Router.current();

    if ( route.path == '/' ) {

        document.body.className = "showBackgroundImage";

    }
};

Partial win here, since this will activate the css, but I need to deactivate when route changes. I have also tried the following within my router.js:

this.route('homepage', {
    path: '/', 
    onAfterAction: function  (argument) {
       // add a class name to body
       document.body.className = "showBackgroundImage";
    }
  });

And CSS in the background standard:

.showBackgroundImage { 
  background: url(bgImage.jpg) no-repeat center center fixed; 
}

Solution

  • This is easily done using iron:router layouts and applying a different class to each pages via routing.

    First you need to define a main-layout such as :

    <template name="mainLayout">
      <!-- optional navbar yield -->
      {{> yield region="navbar"}}
      <div class="{{currentRouteName}}-page">
        {{> yield}}
      </div>
      <!-- optional footer yield -->
      {{> yield region="footer"}}
    </template>
    

    The currentRouteName helper should look something like :

    UI.registerHelper("currentRouteName",function(){
      return Router.current()?Router.current().route.getName():"";
    });
    

    Then I recommend associating a RouteController to your main-layout that will serve as the base class for all of your RouteControllers.

    MainController=RouteController.extend({
      layoutTemplate:"mainLayout",
      // yield navbar and footer templates to navbar and footer regions respectively
      yieldTemplates:{
        "navbar":{
          to:"navbar"
        },
        "footer":{
          to:"footer"
        }
      }
    });
    

    Next you need to make sure that your routes use a controller which is derived from MainController.

    HomeController=MainController.extend({
      template:"home"
    });
    
    Router.map(function(){
      this.route("home",{
        path:"/",
        // optional, by default iron:router is smart enough to guess the controller name,
        // by camel-casing the route name and appending "Controller"
        controller:"HomeController"
      });
    });
    

    So now your home route page is surrounded by a div having an "home-page" class, so you can style it in plain CSS (or better yet, using LESS) :

    .home-page{
      /* your css goes here */
    }
    

    If you define other routes, this will work seamlessly, just inherit from MainController and you'll have a page with route-name-page class automatically.

    Of course, you can use the same style for multiple pages, just specify it in CSS :

    .home-page, .contact-page{
      /* your css goes here */
    }
    

    You can do really nice stuff with layouts, I highly encourage using them.