Reputation: 33
<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
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:
:content
) is always added to the elementcurrentPath
result in the current value of that property being inserted as a class, and are kept dynamically updatedTo 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
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
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