3
    <script type="text/x-handlebars">
        <div class="wrapper">

        <div class="sideMenu">

        {{#link-to 'home'}}Home{{/link-to}}
        {{#link-to 'posts'}}Posts{{/link-to}}
        </div>


        <div class="content">

        {{outlet}}
         </div>

        </div>

    </script>

I am new to ember js. How can I add a class on 'content' class each time when view changes.

3 Answers 3

5

We do something like this:

Ember.Route.reopen({
  activate: function() {
    var cssClass = this.toCssClass();
    // you probably don't need the application class
    // to be added to the body
    if (cssClass !== 'application') {
      Ember.$('body').addClass(cssClass);
    }
  },
  deactivate: function() {
    Ember.$('body').removeClass(this.toCssClass());
  },
  toCssClass: function() {
    return this.routeName.replace(/\./g, '-').dasherize();
  }
});

It would add a class to the body (in your case just use content), that is the same as the current route.

Sign up to request clarification or add additional context in comments.

1 Comment

Nicely done! It might make sense to cache the css class in a property instead of recomputing it in deactivate but that's probably a very minor addition to an elegant solution! Well done, @Asgaroth
0

@torazaburo had some excellent points about @Asgaroth (accepted) answer, but I liked the idea of not having to write this same functionality over and over again. So, what I am providing below is a hybrid of the two solutions plus my own two cents and I believe it addresses @torazaburo concerns regarding the accepted answer.

Let's start with the 2nd point:

I also don't like the idea of polluting Ember.Route

Can you pollute Ember.Route without polluting Ember.Route? (Huh?) Absolutely! :) Instead of overwriting activate, we can write our own function and tell it to run .on(activate) This way, our logic is run, but we are not messing with the built-in/inherited activate hook.

The accepted answer is very procedural, imperative, jQuery-ish, and un-Ember-like.

I have to agree with this as well. In the accepted answer, we are abandoning Ember's data binding approach and instead fall back on the jQuery. Not only that, we then have to have more code in the deactivate to "clean up the mess".

So, here is my approach:

Ember.Route.reopen({
  setContentClass: function(){    
    this.controllerFor('application').set("path", this.routeName.dasherize());
  }.on('activate')
});

We add our own method to the Ember.Route class without overwriting activate hook. All the method is doing is setting a path property on the application controller.

Then, inside application template, we can bind to that property:

    <div {{bind-attr class=":content path"}}>
      {{outlet}}
    </div>

Working solution here

Comments

0

Just bind the currentPath property on the application controller to the class of the element in the template:

<div {{bind-attr class=":content currentPath"}}>
    {{outlet}}
</div>

In case you're not familiar with the {{bind-attr class= syntax in Ember/Handlebars:

  • the class name preceded with a colon (:content) is always added to the element
  • properties such as currentPath result in the current value of that property being inserted as a class, and are kept dynamically updated

To be able to access currentPath in a template being driven by a controller other than the application controller, first add

needs: ['application']

to the controller, which makes the application controller available under the name controllers.application, for use in the bind-attr as follows:

<div {{bind-attr class=":content controllers.application.currentPath"}}>

You may use currentRouteName instead of or in addition to currentPath if that works better for you.

The class name added will be dotted, such as uploads.index. You can refer to that in your CSS by escaping the dot, as in

.uploads\.index { }

Or, if you would prefer dasherized, add a property to give the dasherized path, such as

dasherizedCurrentPath: function() {
    return this.('currentPath').replace(/\./g, '-');
}.property('currentPath')

<div {{bind-attr class=":content dasherizedCurrentPath"}}>

This has been tested in recent versions of ember-cli.

3 Comments

torazaburo, it would be great if you illustrated your idea with a jsbin example. I tried throwing something together and am not successful 100% (emberjs.jsbin.com/tevupe/3/edit?html,css,js,console,output) needs is something used by controllers not routes, so I am not sure exactly how your answer would work in practice
My apologies. I should have said to place the needs in the controller corresponding to the template in question. Have updated my answer. Unfortunately, I don't have time to put together a jsbin at the moment.
I believe what the person was trying to do was to have a div in the application template with an outlet for children templates and that div in the application template would update itself with an appropriate class for whichever route is currently being displayed. Not sure if what you are suggesting would be able to solve that. I tried running with your solution (see comment above) but ran into a brick wall

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.