简体   繁体   中英

Using $routeProvider to redirect to routes outside of Angular

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.

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

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.

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.

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

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM