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 |
