Handling route change errors gracefully

Loading

When using AngularJS routing with $routeProvider, route changes may sometimes fail due to missing templates, failed module loads, or authentication issues. Properly handling these errors ensures a smooth user experience by showing meaningful messages instead of a blank screen or console errors.


1. Why Handle Route Change Errors?

  • Prevent application crashes due to missing resources.
  • Provide user-friendly error messages instead of raw errors.
  • Improve debugging and monitoring by logging issues.
  • Enhance user experience by redirecting to fallback pages.

2. Key AngularJS Events for Handling Route Errors

AngularJS provides two key events that help detect route change issues:

  • $routeChangeError – Fires when an error occurs while resolving a route.
  • $routeChangeStart – Fires before a route change begins, useful for authentication checks.

3. Implementing Global Route Error Handling

Step 1: Listen for $routeChangeError in app.run()

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

app.run(["$rootScope", "$location", function($rootScope, $location) {
$rootScope.$on("$routeChangeError", function(event, current, previous, rejection) {
console.error("Route Change Error:", rejection);

// Redirect user to a custom error page
$location.path("/error");
});
}]);

How This Works:

  • Whenever an error occurs during route changes, it logs the error and redirects the user to /error.

Step 2: Create an Error Route in $routeProvider

Modify the routing configuration to include an error page:

app.config(["$routeProvider", function($routeProvider) {
$routeProvider
.when("/", {
templateUrl: "home.html",
controller: "HomeController"
})
.when("/dashboard", {
templateUrl: "dashboard.html",
controller: "DashboardController",
resolve: {
load: function($q, $timeout) {
var deferred = $q.defer();

// Simulate an error (e.g., module load failure)
$timeout(function() {
deferred.reject("Failed to load dashboard data");
}, 1000);

return deferred.promise;
}
}
})
.when("/error", {
template: "<h2>Error</h2><p>Something went wrong! Please try again later.</p>"
})
.otherwise({
redirectTo: "/"
});
}]);

How This Works:

  • If the /dashboard route fails to load, the error is caught by $routeChangeError, and the user is redirected to /error.

4. Handling Authentication Errors in Route Resolves

Sometimes, users may try to access restricted pages. Handle authentication errors like this:

app.config(["$routeProvider", function($routeProvider) {
$routeProvider
.when("/dashboard", {
templateUrl: "dashboard.html",
controller: "DashboardController",
resolve: {
auth: function($q, AuthService) {
var deferred = $q.defer();
if (AuthService.isAuthenticated()) {
deferred.resolve();
} else {
deferred.reject("Unauthorized access");
}
return deferred.promise;
}
}
});
}]);

app.run(["$rootScope", "$location", function($rootScope, $location) {
$rootScope.$on("$routeChangeError", function(event, current, previous, rejection) {
if (rejection === "Unauthorized access") {
alert("You must log in to access this page.");
$location.path("/");
}
});
}]);

app.service("AuthService", function() {
this.isAuthenticated = function() {
return false; // Change this logic based on real authentication
};
});

How This Works:

  • Before loading /dashboard, AuthService.isAuthenticated() checks user authentication.
  • If unauthorized, $routeChangeError triggers and redirects the user.

5. Displaying a Custom Error Message on the UI

Modify the $rootScope listener to store the error message:

app.run(["$rootScope", "$location", function($rootScope, $location) {
$rootScope.$on("$routeChangeError", function(event, current, previous, rejection) {
console.error("Route Change Error:", rejection);

// Store the error message in rootScope
$rootScope.errorMessage = rejection;

$location.path("/error");
});
}]);

Modify error.html to Show the Error Message

<h2>Error</h2>
<p>{{ errorMessage || "An unexpected error occurred. Please try again." }}</p>

Now the error message is displayed dynamically instead of a generic message.


6. Advanced Error Handling: Logging Errors to a Server

To log errors remotely, modify $routeChangeError to send logs to a backend service:

app.run(["$rootScope", "$location", "$http", function($rootScope, $location, $http) {
$rootScope.$on("$routeChangeError", function(event, current, previous, rejection) {
console.error("Route Change Error:", rejection);

// Send error details to the server
$http.post("/logError", {
url: current.loadedTemplateUrl,
error: rejection
});

$location.path("/error");
});
}]);

This helps monitor and debug errors in production.

Leave a Reply

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