Reputation: 2172
I've written part of a web application in Angular. To ensure that all routes are covered, I wanted to add a redirectTo
property to the $routeProvider
, so that invalid routes are returned to the root of the web application, which doesn't use Angular.
I tried:
$routeProvider.otherwise({
redirectTo: '/'
});
but obviously this only routes in the Angular controlled portion of the URL, so users would be redirected to a URL like http://app.com/angular-part-of-web-app#
, instead of http://app.com
, where I'd like them to go.
I've worked around this by having a blank partial to act as a '404' page, and then a controller which just uses the $window
object to redirect to the desired page:
routes.js
// Redirect to site list.
$routeProvider.when('/404', {
templateUrl: '/partials/404.html',
controller: 'RedirectCtrl'
});
// Redirect to the 404 page.
$routeProvider.otherwise({
redirectTo: '/404'
});
controllers.js
// Controller to redirect users to root page of site.
.controller('RedirectCtrl', ['$scope', '$window', function ($scope, $window) {
$window.location.href = '/';
}]);
However, this is setting off the 'too hacky, must be a better way' alarm bells. Is there a better way to do this in Angular?
EDIT: Angular routes - redirecting to an external site? didn't yield an answer to the same question. I'm going to leave my question open instead of marking it as a duplicate (for now), as with the Angular world moving so fast, the previous answer may no longer be the case.
Upvotes: 37
Views: 61987
Reputation: 356
Hi even though it's been two years, just for some one who search for this answer, simply use window.location.assign('/login'). It's work for me.
Upvotes: 3
Reputation: 5729
You could do something like this:
$routeProvider.when('/404', {
controller: ['$location', function($location){
$location.replace('/');
}]
}).otherwise({
redirectTo: '/404'
});
It is essentially the same thing, only it uses less code.
Upvotes: 19
Reputation: 827
The above solution with /404 does not work for me. This however seems to work
.otherwise({
controller : function(){
window.location.replace('/');
},
template : "<div></div>"
});
PS. I am using Angular 1.2.10
Upvotes: 47
Reputation: 179
None of the answers including the marked answer worked for me. I believe my solution solves your problem as well and I'd share my use-case as well for future readers' reference.
Issue with using the route controller method: When the controller is loaded the routing already have accessed the History API states for me (I use HTML5 mode, not sure whether this affects non-HTML5 mode).
As a result, even though I can forward people to the correct page using window.location.replace('/');, if the user then clicks Back on their browser, it goes to invalid state.
Scenario: We implement multi-page model and I have my admin page module separate from my homepage (non-admin) modules. I have a $location.path('/') somewhere in one of my admin controller, but since homepage isn't packaged into the admin page module, I want to force full page reload when I detect the '/' route.
Solution: We have to intercept at the $routeChangeStart before ngRoute accesses any of the state info. This way we can even specify external href by passing url to redirectTo param in the $route
angular.module('app',['ngRoute'])
.config(['$routeProvider', function($routeProvider) {
$routeProvider
.when('/admin/default', {template: somePageTemplate})
/*
* More admin-related routes here...
*/
.when('/',{redirectTo:'/homepage'}) // <-- We want to intercept this
.otherwise({redirectTo: '/admin/default'});
}])
.controller('MainCtrl',[ // <- Use this controller outside of the ng-view!
'$rootScope','$window',
function($rootScope,$window){
$rootScope.$on("$routeChangeStart", function (event, next, current) {
// next <- might not be set when first load
// next.$$route <- might not be set when routed through 'otherwise'
// You can use regex to match if you have more complexed path...
if (next && next.$$route && next.$$route.originalPath === '/') {
// Stops the ngRoute to proceed
event.preventDefault();
// We have to do it async so that the route callback
// can be cleanly completed first, so $timeout works too
$rootScope.$evalAsync(function() {
// next.$$route.redirectTo would equal be '/homepage'
$window.location.href = next.$$route.redirectTo;
});
}
});
}
]);
Please provide any feedback as I will be using this code myself. Cheers
Reference: https://github.com/angular/angular.js/issues/9607
Upvotes: 5
Reputation: 5747
Not sure what version of Angular JS the accepted answer was written on, but 'redirectTo' property takes in a function. So, why not do something simpler like this:
$routeProvider.otherwise({
redirectTo: function() {
window.location = "/404.html";
}
});
Obviously, you have to create your own 404.html. Or wherever your 404 page is.
Upvotes: 19