How to preload data before navigating to a route?

Loading

Preloading data before navigation ensures that the required data is available before rendering a new route. This improves performance and prevents UI flickering due to missing data. In AngularJS, we can achieve this using resolve in $routeProvider.


1. Why Use Data Preloading?

Prevents UI flickering – Ensures all required data is loaded before the page is displayed.
Improves User Experience – No need to show a loading spinner every time.
Reduces API Calls – Data is fetched once and used throughout the route lifecycle.


2. Using $routeProvider.resolve for Preloading Data

AngularJS provides the resolve property in $routeProvider, which ensures data is fetched before loading the route.

Step 1: Configure Route with resolve

Modify your app.config to include a resolve function:

var app = angular.module("myApp", ["ngRoute"]);

app.config(["$routeProvider", function($routeProvider) {
$routeProvider
.when("/users", {
templateUrl: "users.html",
controller: "UsersController",
resolve: {
userData: function(UserService) {
return UserService.getUsers(); // Fetch users before loading the route
}
}
})
.otherwise({
redirectTo: "/"
});
}]);

How It Works:

  • Before navigating to /users, UserService.getUsers() is executed.
  • The route will load only after the API call is completed.

Step 2: Create a Service for API Calls

Define a UserService to fetch data from an API:

app.service("UserService", ["$http", function($http) {
this.getUsers = function() {
return $http.get("https://jsonplaceholder.typicode.com/users")
.then(response => response.data)
.catch(error => console.error("Error fetching users:", error));
};
}]);

Why Use a Service?

  • Centralizes API calls, making the app more modular.
  • Prevents redundant code in controllers.

Step 3: Inject Preloaded Data into the Controller

Since resolve returns the data to the controller, we inject userData into UsersController:

app.controller("UsersController", ["$scope", "userData", function($scope, userData) {
$scope.users = userData; // Preloaded data is assigned to $scope
}]);

How It Works:

  • The controller receives userData from resolve.
  • $scope.users is populated before rendering the page.

3. Showing a Loading Indicator

If data fetching takes time, display a loading spinner:

Modify the Controller

app.controller("UsersController", ["$scope", "userData", function($scope, userData) {
$scope.isLoading = true;

userData.then(function(data) {
$scope.users = data;
$scope.isLoading = false;
});
}]);

Update the View (users.html)

<div ng-if="isLoading">Loading users...</div>

<ul ng-if="!isLoading">
<li ng-repeat="user in users">{{ user.name }}</li>
</ul>

Now, users will be displayed only after the data is loaded.


4. Alternative Approach Using $rootScope Events

Another way to handle preloading is to use $rootScope.$on("$routeChangeStart"):

app.run(["$rootScope", function($rootScope) {
$rootScope.$on("$routeChangeStart", function(event, next, current) {
console.log("Route change started to:", next.$$route.originalPath);
});

$rootScope.$on("$routeChangeSuccess", function() {
console.log("Route successfully changed.");
});
}]);

Use this method for debugging and tracking route changes.


5. Summary

ApproachProsCons
$routeProvider.resolve Ensures data is available before route loads Initial load may be slow
$rootScope.$on("$routeChangeStart") Can track route changes globally Does not wait for data to load

Leave a Reply

Your email address will not be published. Required fields are marked *