sparxIT Solutions
sparxIT Solutions

Reputation: 33

How can I add a class in ember js

    <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.

Upvotes: 3

Views: 3224

Answers (3)

user663031
user663031

Reputation:

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.

Upvotes: 0

Kalman
Kalman

Reputation: 8121

@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

Upvotes: 0

Asgaroth
Asgaroth

Reputation: 4334

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.

Upvotes: 5

Related Questions