Abstract
In this article, I solve the problem of how to toggle an icon between the "open" state and "closed" state on an accordion in Angular JS in three different ways.
The Problem
Update 2020-08-22: This article was written in 2015, when there was only one major version of Angular JS. In 2016, a new version of Angular came out (Angular 2, or just "Angular"). This article is specifically talking about Angular JS 1, since that's all that existing at time of writing.
I was helping a colleague with a problem he was trying to solve using Angular JS the other day. He was implementing an accordion effect, where clicking on a heading would show the panel beneath the heading. On the heading, there is an icon which points right if the panel is closed, and down if the panel is open.
The solution that he started with used a switch statement and looked something like this.
<span ng-switch="panel.closed"> <i ng-switch-when="true" class="glyphicon glyphicon-chevron-right"></i> <i ng-switch-when="false" class="glyphicon glyphicon-chevron-down"></i> </span> First example
Improving this with ng-class
Using ng-switch works, but if you look at the two cases then you notice that the only difference between the two is the class indicating which icon to use. We can simplify this example by replacing the ng-switch with ng-class.
<span> <i ng-class="panel.closed ? 'glyphicon-chevron-right' : 'glyphicon-chevron-down'" class="glyphicon"></i> </span> Second example
I am lucky enough to only be supporting modern browsers
If you're only supporting modern browsers, then you can take advantage of CSS3 properties. This lets us specify in our style sheet that if the icon has a 'open-panel-icon' class, then we want to rotate it. The cool thing about this approach is that we can combine it with the CSS3 transition property to animate changing from one icon to the next.
<span> <i ng-class="{'open-panel-icon': !panel.closed}" class="glyphicon glyphicon-chevron-right panel-icon" ></i> </span> Third example
.panel-icon { transition: transform 0.3s; transform: rotate(0deg); } .open-panel-icon { transform: rotate(90deg); }
I've made a demo of these three approaches on Plunkr that you can play with here: Demo on Plunkr