When navigating between routes in an AngularJS application, you may encounter an issue where $scope variables reset or get lost. This can cause UI inconsistencies, unexpected data loss, and poor user experience.
This guide explains why $scope is lost when switching routes and provides step-by-step solutions to fix it.
1. Why $scope Variables Get Lost?
In AngularJS, $scope is tied to the lifecycle of the controller. When switching routes, the previous controller is destroyed, and a new controller instance is created. This means that any variables stored in $scope will be lost.
| Issue | Cause | Solution |
|---|---|---|
| Scope resets on route change | Controllers are reinitialized when navigating between views. | Use a shared service or $rootScope for persistence. |
| Data lost on page refresh | Browser refresh clears in-memory $scope variables. | Store data in localStorage or session storage. |
| Scope not persisting in nested views | Scope exists only in its controller. | Use a parent controller with shared scope. |
| Form data lost on navigation | The controller is destroyed when switching views. | Use a factory/service to persist form data. |
2. Fixing $scope Reset on Route Changes
Fix 1: Use a Shared Service for Data Persistence
Since $scope is specific to a controller, using an AngularJS service or factory can help persist data across route changes.
Step 1: Create a Shared Service
app.factory('SharedDataService', function() {
var sharedData = {}; // Object to store data persistently
return {
getData: function() {
return sharedData;
},
setData: function(data) {
sharedData = data;
}
};
});
Step 2: Use It in Controllers
app.controller('FirstCtrl', function($scope, SharedDataService) {
$scope.data = { message: "Hello, World!" };
$scope.saveData = function() {
SharedDataService.setData($scope.data);
};
});
app.controller('SecondCtrl', function($scope, SharedDataService) {
$scope.data = SharedDataService.getData(); // Retrieve shared data
});
Step 3: Bind to Views
<div ng-controller="FirstCtrl">
<input type="text" ng-model="data.message">
<button ng-click="saveData()">Save Data</button>
</div>
<div ng-controller="SecondCtrl">
<p>Stored Message: {{ data.message }}</p>
</div>
Why?
Services and factories persist data because they follow the Singleton Pattern in AngularJS.
Fix 2: Store Data in $rootScope
$rootScope is accessible throughout the entire application, making it useful for global data storage.
Example
app.controller('FirstCtrl', function($scope, $rootScope) {
$rootScope.sharedMessage = "Hello, World!";
});
app.controller('SecondCtrl', function($scope, $rootScope) {
$scope.message = $rootScope.sharedMessage; // Data persists across views
});
When to Use?
- When data needs to be globally accessible.
- Not recommended for large applications (as
$rootScopecan become difficult to manage).
Fix 3: Use Local Storage for Persistent Data
If you need persistent data even after a page refresh, use localStorage or sessionStorage.
Example Using localStorage
app.controller('FirstCtrl', function($scope) {
$scope.data = { message: "Hello, World!" };
$scope.saveData = function() {
localStorage.setItem('message', $scope.data.message);
};
});
app.controller('SecondCtrl', function($scope) {
$scope.message = localStorage.getItem('message') || "No data saved yet!";
});
Example Using sessionStorage
sessionStorage.setItem('username', 'JohnDoe');
var username = sessionStorage.getItem('username');
Why?
localStoragepersists data even after a page reload.sessionStorageonly keeps data for the duration of the session.
Fix 4: Prevent Controller Reload Using reloadOnSearch: false
If $scope is lost only when query parameters change, prevent unnecessary controller reloads.
Modify Your Route Configuration
$routeProvider
.when('/page1', {
templateUrl: 'page1.html',
controller: 'Page1Ctrl',
reloadOnSearch: false // Prevents unnecessary reload
});
When to Use?
- When navigating between routes without losing scope due to search parameter changes.
Fix 5: Use a Parent Controller
When switching between nested views, you can use a parent controller to hold persistent data.
Example
<div ng-controller="ParentCtrl">
<div ng-view></div> <!-- Child views will use ParentCtrl's scope -->
</div>
app.controller('ParentCtrl', function($scope) {
$scope.sharedData = { message: "Hello, Persistent Data!" };
});
<div ng-controller="ChildCtrl">
<p>{{ sharedData.message }}</p> <!-- Inherits from ParentCtrl -->
</div>
Why?
The child controller will inherit $scope.sharedData from the parent controller, preventing data loss.
3. Summary of Fixes
| Fix | Solution |
|---|---|
| Use a Shared Service | Store data in a service/factory for persistence across views. |
Store Data in $rootScope | Use $rootScope for globally accessible data. |
| Use Local Storage | Store persistent data that survives page refresh. |
| Prevent Controller Reload | Set reloadOnSearch: false in $routeProvider. |
| Use a Parent Controller | Place shared data in a parent scope for nested views. |
