When using ng-repeat
in AngularJS, you might encounter situations where the list does not render correctly, updates are not reflected, or expected data is missing. This can happen due to scoping issues, incorrect data structure, or Angular not detecting changes properly.
1. Common Causes of ng-repeat
Not Rendering Data
Here are the most frequent reasons why ng-repeat
might not work as expected:
Cause 1: Data Is Not Available When ng-repeat
Runs
AngularJS initializes ng-repeat
before asynchronous data (e.g., from an API) is loaded. If the data is not yet available, ng-repeat
renders nothing.
Example (Issue)
<ul>
<li ng-repeat="item in items">{{ item.name }}</li>
</ul>
app.controller('MainCtrl', function($scope, $http) {
// Fetch data asynchronously
$http.get('/api/items').then(function(response) {
$scope.items = response.data;
});
});
Problem: When ng-repeat
runs, $scope.items
is undefined
, so no data appears.
Solution: Use ng-if
or ng-show
to wait until data loads.
<ul ng-if="items.length">
<li ng-repeat="item in items">{{ item.name }}</li>
</ul>
This ensures ng-repeat
renders only when items
is available.
Cause 2: Using ng-repeat
on the Wrong Data Type
ng-repeat
works only with arrays. If items
is undefined
, null
, or an object, it won’t work.
Example (Issue)
<div ng-repeat="item in items">{{ item.name }}</div>
$scope.items = { name: "Item1" }; // Not an array
Problem: items
is an object, but ng-repeat
expects an array.
Solution: Make sure items
is an array.
$scope.items = [{ name: "Item1" }];
Cause 3: ng-repeat
with Track By Key Issues
By default, ng-repeat
tracks elements by index, which can cause performance issues. If Angular reuses elements incorrectly, items may not update properly.
Example (Issue)
<li ng-repeat="item in items">{{ item.name }}</li>
If items
updates dynamically, Angular might not detect changes correctly.
Solution: Use track by
to track unique IDs.
<li ng-repeat="item in items track by item.id">{{ item.name }}</li>
This ensures Angular efficiently tracks and updates items.
Cause 4: Using Primitive Values Without Two-Way Binding
If items
is an array of primitive values (numbers or strings), ng-repeat
doesn’t bind them correctly.
Example (Issue)
<li ng-repeat="item in items">
<input type="text" ng-model="item">
</li>
$scope.items = ["One", "Two", "Three"];
Problem: Since strings are immutable, Angular can’t track changes properly.
Solution: Use objects instead of primitive values.
$scope.items = [{ name: "One" }, { name: "Two" }, { name: "Three" }];
<li ng-repeat="item in items">
<input type="text" ng-model="item.name">
</li>
Cause 5: $scope
Reference Issues
If ng-repeat
is inside a nested scope (like inside a directive or ng-controller
), the $scope
might not have access to the correct data.
Example (Issue)
<div ng-controller="ChildCtrl">
<ul>
<li ng-repeat="item in items">{{ item.name }}</li>
</ul>
</div>
app.controller('ChildCtrl', function($scope) {
$scope.items = []; // Not inherited from parent
});
Problem: If items
is defined only in the parent controller, the child controller doesn’t inherit it automatically.
Solution: Use $parent
in ng-repeat
.
<ul>
<li ng-repeat="item in $parent.items">{{ item.name }}</li>
</ul>
OR use a shared service to manage data across controllers.
Cause 6: AngularJS Not Detecting Array Changes ($watch
Issue)
Angular does not detect changes when modifying an array without using $scope
methods.
Example (Issue)
$scope.items = ["A", "B", "C"];
$scope.items.push("D"); // Angular might not detect this
Problem: Directly modifying the array might not trigger a UI update.
Solution: Use $scope.$apply()
or angular.copy()
$scope.$apply(function() {
$scope.items.push("D");
});
OR
$scope.items = angular.copy($scope.items);
This forces AngularJS to detect changes.
Cause 7: ng-repeat
Inside ng-if
Causing Reinitialization
If ng-repeat
is inside an ng-if
, the list gets reloaded every time the condition changes.
Example (Issue)
<div ng-if="showList">
<ul>
<li ng-repeat="item in items">{{ item.name }}</li>
</ul>
</div>
Problem: If showList
toggles, ng-repeat
will reinitialize every time.
Solution: Use ng-show
Instead of ng-if
<div ng-show="showList">
<ul>
<li ng-repeat="item in items">{{ item.name }}</li>
</ul>
</div>
ng-show
keeps the list in memory instead of reloading it.
4. Summary of Fixes
Issue | Fix |
---|---|
Data is not available when ng-repeat runs | Use ng-if="items.length" to wait until data loads |
ng-repeat used on an object instead of an array | Ensure items is an array |
ng-repeat list not updating properly | Use track by item.id |
Primitive values (strings, numbers) not binding properly | Use objects instead of primitive values |
$scope reference issues inside directives/controllers | Use $parent.items or a shared service |
Angular not detecting array changes | Use $scope.$apply() or angular.copy() |
ng-if causing ng-repeat to reload | Use ng-show instead of ng-if |