Question
You have an array rendered inside a ul, with one li for each element, and a controller property called selectedIndex. How can you add a CSS class only to the li whose index matches selectedIndex in AngularJS?
For example, instead of manually duplicating the li markup, adding a class to one copy, and using ng-show / ng-hide to display only one version per index, what is the recommended AngularJS approach?
A simplified version might look like this:
<ul>
<li ng-repeat="item in items">
{{ item.name }}
</li>
</ul>
And in the controller:
$scope.selectedIndex = 2;
Short Answer
By the end of this page, you will understand how AngularJS conditionally applies CSS classes using ngClass, especially when rendering lists with ngRepeat. You will also see how $index works, how to compare it with selectedIndex, and why this is better than duplicating HTML with ng-show and ng-hide.
Concept
In AngularJS, the standard way to conditionally apply a CSS class is with the ngClass directive.
When you render a list using ngRepeat, AngularJS gives you access to a special local variable called $index, which represents the current item's position in the loop. If your controller stores a selectedIndex, you can compare $index to that value and apply a class when they match.
This matters because:
- It keeps your template small and readable.
- It avoids duplicated markup.
- It separates structure from styling.
- It makes updates easier when selection changes.
Instead of rendering two versions of the same li, you render one li and let AngularJS decide whether it should include a class.
This is a common UI pattern in real applications:
- selected menu items
- active tabs
- highlighted search results
- chosen rows in a table
- current step in a wizard
In short, ngClass is the AngularJS tool for dynamic styling based on application state.
Mental Model
Think of each li as a student in a line, and selectedIndex as the number of the student who should wear a badge.
You do not create two copies of every student—one with a badge and one without. Instead, you keep one student and simply ask:
- “Is this the selected one?”
- If yes, give them the badge.
- If no, do nothing.
In AngularJS, ngRepeat gives each item a number ($index), and ngClass decides whether that item gets the CSS "badge" class.
Syntax and Examples
The most common syntax is:
<li ng-repeat="item in items"
ng-class="{ selected: $index === selectedIndex }">
{{ item.name }}
</li>
Example
<ul>
<li ng-repeat="item in items"
ng-class="{ selected: $index === selectedIndex }">
{{ item.name }}
</li>
</ul>
$scope.items = [
{ name: 'Apple' },
{ name: 'Banana' },
{ name: 'Cherry' }
];
$scope.selectedIndex = 1;
.selected {
background-color: #dbeafe;
font-weight: bold;
}
What this does
ng-repeat="item in items"loops over the array.$indexis the current item's index:0,1,2, and so on.ng-class="{ selected: $index === selectedIndex }"adds theselectedclass only when the condition is true.
So if selectedIndex is 1, the second li gets the selected class.
Alternative syntax
AngularJS also supports other ngClass forms.
String form
<li ng-repeat="item in items"
ng-class="$index === selectedIndex ? 'selected' : ''">
{{ item.name }}
</li>
Multiple classes with object syntax
<li ng-repeat="item in items"
ng-class="{
selected: $index === selectedIndex,
evenRow: $index % 2 === 0
}">
{{ item.name }}
</li>
The object form is usually the clearest for conditional classes.
Step by Step Execution
Consider this example:
<ul>
<li ng-repeat="item in items"
ng-class="{ selected: $index === selectedIndex }">
{{ item.name }}
</li>
</ul>
$scope.items = [
{ name: 'A' },
{ name: 'B' },
{ name: 'C' }
];
$scope.selectedIndex = 2;
Step-by-step
- AngularJS reads
itemsand startsngRepeat. - For the first item:
item.nameisA$indexis0- condition is
0 === 2, which isfalse - no
selectedclass is added
- For the second item:
item.nameisB$indexis1- condition is
1 === 2, which isfalse - no
selectedclass is added
- For the third item:
item.nameisC$indexis2- condition is
2 === 2, which istrue - AngularJS adds the
selectedclass
Final rendered result
It behaves like this:
<ul>
<li>A</li>
<li>B</li>
<li class="selected">C</li>
</ul>
If selectedIndex later changes to 0, AngularJS updates the classes automatically during digest processing, and the first item becomes selected instead.
Real World Use Cases
Conditional classes are used everywhere in AngularJS interfaces.
Navigation menus
Highlight the current menu item:
<li ng-repeat="link in links"
ng-class="{ active: $index === selectedIndex }">
{{ link.label }}
</li>
Tabs
Mark the open tab:
<button ng-repeat="tab in tabs"
ng-class="{ activeTab: $index === selectedIndex }">
{{ tab.title }}
</button>
Search results
Emphasize the currently focused result for keyboard navigation.
Data tables
Highlight the selected row in an admin dashboard.
Image galleries
Apply a border to the currently selected thumbnail.
Forms and validation
Add classes like error, valid, or dirty based on state.
In all of these cases, the idea is the same: the class reflects data or UI state.
Real Codebase Usage
In real AngularJS projects, developers commonly use ngClass with simple conditions and keep the selection state in the controller.
Common pattern: selected index
<li ng-repeat="item in items"
ng-class="{ selected: $index === selectedIndex }"
ng-click="selectedIndex = $index">
{{ item.name }}
</li>
This is a standard pattern for clickable lists.
Guarding against invalid values
Developers often make sure selectedIndex is valid before using it.
if ($scope.selectedIndex < 0 || $scope.selectedIndex >= $scope.items.length) {
$scope.selectedIndex = 0;
}
Using item identity instead of index
In larger codebases, developers sometimes track the selected item by ID instead of index, because indexes can change if the list is filtered, sorted, or reordered.
<li ng-repeat="item in items"
ng-class="{ selected: item.id === selectedItemId }">
{{ item.name }}
</li>
Pairing with event handlers
<li ng-repeat="item in items"
ng-class="{ selected: $index === selectedIndex }"
ng-mouseenter="selectedIndex = $index">
{{ item.name }}
</li>
Keeping templates clean
If the condition becomes too long, teams sometimes move logic into a controller method:
<li ng-repeat="item in items" ng-class="{ selected: isSelected($index) }">
{{ item.name }}
</li>
$scope.isSelected = function(index) {
return index === $scope.selectedIndex;
};
This should stay simple. If the logic is trivial, inline conditions are usually easier to read.
Common Mistakes
Here are common beginner mistakes when conditionally applying classes in AngularJS.
1. Duplicating markup with ng-show and ng-hide
Not recommended
<li ng-repeat="item in items" ng-show="$index === selectedIndex" class="selected">
{{ item.name }}
</li>
<li ng-repeat="item in items" ng-hide="$index === selectedIndex">
{{ item.name }}
</li>
This creates unnecessary duplication and makes templates harder to maintain.
Better
<li ng-repeat="item in items"
ng-class="{ selected: $index === selectedIndex }">
{{ item.name }}
</li>
2. Using class for dynamic logic
Broken approach:
<li class="$index === selectedIndex ? 'selected' : ''">
{{ item.name }}
</li>
AngularJS does not evaluate expressions inside the normal class attribute like that.
Use ngClass instead.
3. Confusing = with comparison
Broken code:
<li ng-class="{ selected: $index = selectedIndex }">
{{ item.name }}
</li>
Use comparison:
<li ng-class="{ selected: $index === selectedIndex }">
{{ item.name }}
</li>
4. Forgetting that $index comes from ngRepeat
$index only exists inside the ng-repeat scope.
Broken example:
<p ng-class="{ selected: $index === selectedIndex }">Hello</p>
This will not work unless the element is inside an ngRepeat block.
5. Depending on index when list order can change
If items are sorted or filtered, the selected index may no longer point to the same item.
Safer option:
<li ng-repeat="item in items"
ng-class="{ selected: item.id === selectedItemId }">
{{ item.name }}
</li>
6. Forgetting to define the CSS class
Even if AngularJS adds the class, nothing visible happens unless your CSS exists.
.selected {
background: yellow;
}
Comparisons
Here is how ngClass compares with related AngularJS approaches.
| Approach | Best for | Good choice here? | Notes |
|---|---|---|---|
ng-class | Conditionally adding/removing CSS classes | Yes | Clean, readable, standard solution |
class | Static classes only | No | Does not handle AngularJS conditional logic by itself |
ng-show / ng-hide | Showing or hiding entire elements | No | Changes visibility, not styling |
ng-style | Dynamic inline styles | Sometimes | Useful for one-off styles, but classes are usually cleaner |
ng-if | Creating/removing elements from the DOM | No | Too heavy if you only need a class |
ngClass vs ngStyle
<li ng-class="{ selected: $index === selectedIndex }">
vs.
<li ng-style="{ 'font-weight': $index === selectedIndex ? 'bold' : 'normal' }">
Use ngClass when:
- styling belongs in CSS
- multiple style rules are involved
- you want cleaner templates
Use ngStyle when:
- you need a small dynamic inline style
- the value is highly variable, such as width or color from data
Index-based selection vs ID-based selection
| Technique | Advantage | Drawback |
|---|---|---|
selectedIndex | Simple and easy for small lists | Can break if list order changes |
selectedItemId | More stable in real apps | Requires each item to have an ID |
For a beginner example, selectedIndex is perfect. In larger apps, IDs are often safer.
Cheat Sheet
<li ng-repeat="item in items"
ng-class="{ selected: $index === selectedIndex }">
{{ item.name }}
</li>
Key points
- Use
ngClassfor conditional CSS classes. - Use
$indexinsidengRepeat. - Compare
$indexwithselectedIndex. - Prefer object syntax for readability.
Common forms
Object syntax
ng-class="{ selected: $index === selectedIndex }"
Ternary syntax
ng-class="$index === selectedIndex ? 'selected' : ''"
Multiple classes
ng-class="{ selected: isSelected, disabled: isDisabled }"
Rules
$indexexists only insidengRepeat.ng-show/ng-hideare for visibility, not for styling.- Define the CSS class in your stylesheet.
- Use
===for comparison.
Safer alternative for changing lists
<li ng-repeat="item in items"
ng-class="{ selected: item.id === selectedItemId }">
{{ item.name }}
</li>
FAQ
How do I add a class to one item in an AngularJS ngRepeat?
Use ng-class and compare $index with your selected value.
<li ng-repeat="item in items" ng-class="{ selected: $index === selectedIndex }">
Is ngClass better than ng-show and ng-hide for this?
Yes. ngClass is the correct tool when you want to style an element differently. ng-show and ng-hide are for visibility, not class changes.
What is $index in AngularJS?
$index is a local variable available inside ngRepeat. It contains the current loop position starting from 0.
Can I use a class name string instead of object syntax in ngClass?
Yes.
ng-class="$index === selectedIndex ? 'selected' : ''"
But object syntax is often easier to read and extend.
Why is my class not appearing visually?
Possible reasons:
- the condition is false
- the CSS class is not defined
selectedIndexhas the wrong value- the element is not inside
ngRepeat, so$indexis unavailable
Should I use index or item ID for selection?
For simple lists, index is fine. For lists that can be sorted, filtered, or reordered, using an item ID is usually safer.
Can I change the selected item when the user clicks?
Yes.
<li ng-repeat="item in items"
ng-class="{ selected: $index === selectedIndex }"
ng-click="selectedIndex = $index">
{{ item.name }}
</li>
Mini Project
Description
Build a selectable list of items in AngularJS. The user should be able to click any item in the list, and the clicked item should receive a highlight class. This project demonstrates how ngRepeat, $index, ngClick, and ngClass work together in a practical UI pattern.
Goal
Create an AngularJS list where exactly one item is highlighted based on selectedIndex, and clicking an item changes the selection.
Requirements
- Render a list of items using
ngRepeat. - Store the selected item position in
selectedIndex. - Apply a CSS class only when
$index === selectedIndex. - Update
selectedIndexwhen a user clicks an item. - Add visible CSS so the selected item is clearly highlighted.
Keep learning
Related questions
Angular ngClass Conditional Class Binding Explained
Learn how to use Angular ngClass for conditional classes, fix common binding mistakes, and understand why this template error happens.
CSS :not() Selector for Elements Without a Class or Attribute
Learn how to use the CSS :not() selector to target elements that do not have a specific class or attribute, with examples and common pitfalls.
CSS Font Scaling Relative to Container Size: %, em, rem, vw, and Responsive Text
Learn how CSS font scaling really works and how to make text responsive using %, em, rem, vw, clamp(), and media queries.