Skip to main content
Ben Nadel at cf.Objective() 2017 (Washington, D.C.) with: Jake Scott
Ben Nadel at cf.Objective() 2017 (Washington, D.C.) with: Jake Scott

$route redirectTo Does Not Break The Back Button In AngularJS

By
Published in Comments (3)

When defining routes in an AngularJS application, you can provide routes that do nothing but redirect to other routes. This works for both explicitly defined routes as well as for the catch-all "otherwise" route. One awesome feature of the "redirectTo" property, which I just discovered, is that it will not break the browser's back-button.

Run this demo in my JavaScript Demos project on GitHub.

Under the hood, the redirectTo action is implemented using the $location.replace() method. This method is used to replace the current location rather than pushing a new location onto the history stack. By not adding to the history stack, AngularJS allows the browser's back-button to circumvent the current location.

To see this in action, I've created a tiny $route demo that contains two "redirectTo" route configurations:

  • /people => /people/friends
  • "catch all" => /home

The first one allows the application to link users to a general section [people] without having to be overly specific. The second simply catches any missing route and redirects the user back to the homepage.

The important thing to know (which you can't see from the code itself) is that after the "redirectTo" is executed, the user's back and forward buttons (on their browser) jump over the redirect entirely.

<!doctype html>
<html ng-app="Demo">
<head>
	<meta charset="utf-8" />

	<title>
		$route redirectTo Does Not Break The Back Button In AngularJS
	</title>
</head>
<body ng-controller="AppController">

	<h1>
		$route redirectTo Does Not Break The Back Button In AngularJS
	</h1>

	<p>
		<a href="#/home">Home</a>
		&mdash;
		<a href="#/people">People</a>
		&mdash;
		<a href="#/broken">Broken link</a>
	</p>

	<p>
		<strong>Action</strong>: {{ routeAction }}
	</p>


	<!-- Load scripts. -->
	<script type="text/javascript" src="../../vendor/angularjs/angular-1.3.8.min.js"></script>
	<script type="text/javascript" src="../../vendor/angularjs/angular-route-1.3.8.min.js"></script>
	<script type="text/javascript">

		// Create an application module for our demo.
		var app = angular.module( "Demo", [ "ngRoute" ] );


		// -------------------------------------------------- //
		// -------------------------------------------------- //


		// I setup the routes for the application.
		app.config(
			function( $routeProvider ) {

				$routeProvider
					.when(
						"/home",
						{
							action: "home"
						}
					)

					// Notice that this route doesn't actually map to an action. Rather,
					// it redirects to a sub-route off of the current route.
					// --
					// NOTE: Under the hood, this uses $location.replace(), which is
					// intended to keep the back-button working properly with redirects.
					.when(
						"/people",
						{
							redirectTo: "/people/friends"
						}
					)

					.when(
						"/people/friends",
						{
							action: "people.friends"
						}
					)
					.when(
						"/people/enemies",
						{
							action: "people.enemies"
						}
					)
					.otherwise({
						redirectTo: "/home"
					})
				;

			}
		);


		// -------------------------------------------------- //
		// -------------------------------------------------- //


		// I control the root of the application.
		app.controller(
			"AppController",
			function( $scope, $route, $routeParams ) {

				$scope.routeAction = null;

				// I listen for route-change events.
				$scope.$on(
					"$routeChangeSuccess",
					function handleRouteChangeEvent( event ) {

						var current = $route.current;

						console.log( "Route change event:", current.originalPath );

						// If the current route doesn't contain an action, then it will,
						// in all likelihood, be redirected to another route that does
						// contain a valid action (configured in $routeProvider).
						if ( ! current.action ) {

							console.warn(
								"Route does not contain an action.",
								"Redirecting to another route."
							);

						}

						// Store our current action for output.
						$scope.routeAction = current.action;

					}
				);

			}
		);

	</script>

</body>
</html>

Since the point of this demo is to showcase browser behavior (and the AngularJS integration), the output is not immediately obvious. As such, I suggest watching the video or trying out the demo.

redirectTo does not break the back button in an AngularJS application.

In any case, it's awesome that this is how AngularJS implemented the redirectTo feature. I wish I had known about this earlier - I have put way too much redirect logic into my Controllers when it could have been easily handled in the route itself.

Want to use code from this post? Check out the license.

Reader Comments

1 Comments

Hi,
I have a single page angularapp.
In the home page : http://localhost:8080/APPNAME/#/home.
When user selects a radio button,

The link is http://localhost:8080/APPNAME/#/xxxx/Multiple. Here the user makes multiple selections and clicks "SUBMIT".

We display the results, still the URL is
http://localhost:8080/APPNAME/#/xxxx/Multiple.

From here when the user clicks browser back button, the app is going to
'http://localhost:8080/APPNAME/#/home'
But I want to stay at http://localhost:8080/APPNAME/#/xxxx/Multiple.

How to detect if user pressed browser back button in Angualrjs.

1 Comments

Hi,
Awesome post, I want to know can we do the same,If i am using component router in my app(Angular version 1.5.x)

I believe in love. I believe in compassion. I believe in human rights. I believe that we can afford to give more of these gifts to the world around us because it costs us nothing to be decent and kind and understanding. And, I want you to know that when you land on this site, you are accepted for who you are, no matter how you identify, what truths you live, or whatever kind of goofy shit makes you feel alive! Rock on with your bad self!
Ben Nadel