-2

I want to add the current controller/action as a class to the <body> tag in my application layout template.

Here is an example of what I am trying to achieve:

# router.coffee
App.Router.map ->
  @resource 'products'

# application.hbs
<!DOCTYPE html>
<html>
<body class={{current-route-goes-here}}>
...
</body>
</html>

The desired result would be <body class="products">

How can I add this logic to my layout?

Andrew
  • 227,796
  • 193
  • 515
  • 708
  • 3
    What do you mean by layout? Can you add some more explanation? You aren't new to the site you know the rules... – Patsy Issa Jun 24 '15 at 15:09
  • Sorry, my fault, I thought it was obvious, but maybe the word layout means different things to different people. I mean the tag in application.js.hbs – Andrew Jun 24 '15 at 15:25
  • You want to add a class to the `` tag from the controller? – Patsy Issa Jun 24 '15 at 15:27
  • If you can edit your question with what you currently have, the controller you are trying to do this from I ll vote on reopening and give you an answer. Also are you using the `ember-cli`? – Patsy Issa Jun 24 '15 at 15:29
  • I want to add the name of the route/controller as a class on the body tag. So if the route was "products" the class would be "products" – Andrew Jun 24 '15 at 15:42
  • The body tag is outside the scope of the application route/controller and such, you will need to manually set the class from the `didInsertElement` hook, make sure to wrap it in an [Ember.run](http://emberjs.com/api/classes/Ember.run.html) – Patsy Issa Jun 24 '15 at 15:44
  • I'm not using ember-cli but if I had an example then I could convert it myself. – Andrew Jun 24 '15 at 15:44
  • Yeah, I figured it's not an easy answer to an easy question because I haven't found any examples of how to do this. Can you provide a code sample for what you are talking about? – Andrew Jun 24 '15 at 15:48
  • I have updated my question to add some code samples. Please re-open this post. – Andrew Jun 24 '15 at 18:15
  • Andrew, Can you please let us know what problem are you trying to solve here? Looks like there should be a much easy logic to solve the problem like adding the class to the view that is interested inside the body tag for each specific route instead of tweaking the class of the body tag – phkavitha Jun 24 '15 at 20:24
  • @phkavitha There may be an easier approach, but this sort of thing is usually pretty easy in other frameworks. I'm simply trying to dynamically retrieve the current route name so that I can display it in a template. – Andrew Jun 24 '15 at 20:37
  • Andrew, In that case, there is a way to change the class of the body tag. But, I'm not sure whether it's the most optimistic way. You can implement "activate" and "deactivate" function in every route except the "application" route. Inside the "activate" function, you can get the current route name using "this.get("routeName") and add it to the body tag. In the "deactivate" function, remove the corresponding class. For more reference: http://stackoverflow.com/questions/20781154/add-css-classes-to-body-in-ember-js Hope it helps. – phkavitha Jun 25 '15 at 00:26

2 Answers2

0

The body tag isn't in the ember application scope, if you have to change it you need to do it via javascript.

The route mixin that should be mixed with your top routes (ie products and not products.index):

App.RouteClassMixin = Ember.Mixin.create({
  setupController: function(controller) {
    controller.set('routeName', this.routeName);
  },
  deactivate: function() {
    this.controllerFor(this.routeName).set('routeName', '');
  }
});

And the controller mixin:

App.ControllerClassMixin = Ember.Mixin.create({
  routeName: '',
  init: function() {
    this.handleBodyClass();
  },
  handleBodyClass: function() {
    var routeName = this.get('routeName');
    this.$('body').attr('class', routeName);
  }.observes('routeName')
});

This is untested code, let me know if you run into any problems.

Patsy Issa
  • 11,113
  • 4
  • 55
  • 74
  • You could also use the `currentRouteName` property on the application controller, as documented [here](http://guides.emberjs.com/v1.10.0/understanding-ember/debugging/#toc_get-current-route-name-path). So if all he wanted to do was add a class name to the body, he would just have to add a single observer to the application controller. – GJK Jun 25 '15 at 18:59
  • @GJK that would also cause it to fire on `product.index` etc resulting in broken classes – Patsy Issa Jun 26 '15 at 06:25
0

I'm unable to comment directly on @Kitler's answer. I suggest one small change: use addClass() instead of attr(). The latter will blow away any other classes already on the body.

brian
  • 167
  • 4