meteor js iron router: apply CSS change whenever route changes
Asked Answered
I

3

5

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; 
}
Intramundane answered 22/8, 2014 at 22:14 Comment(0)
C
6

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.

Canterbury answered 22/8, 2014 at 22:34 Comment(3)
To add to this method: sometimes you need to alter the body class for a certain layout to work. To do so, use rendered and destroyed callbacks of said layout, i.e.: Template.layout.rendered = function() {$('body').addClass('layoutBody')}; and then Template.layout.destroyed = function() {$('body').removeClass('layoutBody')};Strickle
As of Iron Router 1.0 (perhaps earlier), use Router.current().route.getName() for getting the current route name (notice the change from route.name to route.getName()).Unmeet
Thanks for noticing deprecated code, I updated my answer. To further explain this, routes are now functions rather than plain objects, and in JS name is a default property for functions containing the function name, hence the required new getName() getter.Canterbury
P
3

I've done this exact thing using iron-router and jQuery. Here's what I did.

/**
 * Add a background image for certain routes.
 */
var setBackground = function () {
  var route = this.route.name;
  var routes = ['homepage', 'contact'];

  if (_.contains(routes, route)) {
    $('body').addClass('showBackgroundImage');
  } else {
    $('body').removeClass('showBackgroundImage');
  }
};

Router.onBeforeAction(setBackground);
Pasquinade answered 22/8, 2014 at 22:32 Comment(0)
R
1

Using Meteor 1.2 and iron-router, here's what worked really easy for me:

Router.onBeforeAction(function() {
  $('body').addClass(this.route.options.template);
  this.next();
});

That's it!

This will take the name from the template your are using and assign it to the body.

How easy and convenient!!

If you want to assign a specific name instead of the template name, just replace this.route.options.template with this.route.getName() and give a name to your route.

Repairman answered 22/10, 2015 at 17:37 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.