37

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.

4

5 回答 5

47

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

于 2014-03-11T09:21:23.937 回答
19

你可以这样做:

$routeProvider.when('/404', {
    controller: ['$location', function($location){
        $location.replace('/');
    }]
}).otherwise({
    redirectTo: '/404'
});

它本质上是一样的,只是它使用的代码更少。

于 2013-10-11T15:41:16.560 回答
19

不确定接受的答案写在哪个版本的 Angular JS 上,但 'redirectTo' 属性接受一个函数。那么,为什么不做一些像这样更简单的事情:

$routeProvider.otherwise({
    redirectTo: function() {
        window.location = "/404.html";
    }
});

显然,您必须创建自己的 404.html。或者您的 404 页面在哪里。

于 2014-06-12T04:45:15.913 回答
5

包括标记答案在内的所有答案都不适合我。我相信我的解决方案也可以解决您的问题,我也会分享我的用例以供将来的读者参考。

使用路由控制器方法 的问题:加载控制器时,路由已经为我访问了 History API 状态(我使用 HTML5 模式,不确定这是否会影响非 HTML5 模式)。

结果,即使我可以使用 window.location.replace('/'); 将人们转发到正确的页面;如果用户随后在浏览器上单击返回,它也会进入无效状态。

场景:我们实现了多页面模型,我的管理页面模块与我的主页(非管理)模块分开。我的一个管理控制器中有一个 $location.path('/') ,但是由于主页未打包到管理页面模块中,因此我想在检测到“/”路由时强制重新加载整个页面。

解决方案: 我们必须在 ngRoute 访问任何状态信息之前在 $routeChangeStart 处进行拦截。这样我们甚至可以通过将 url 传递给 $route 中的 redirectTo 参数来指定外部 href

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;
        });
      }
    });
  }
]);

请提供任何反馈,因为我将自己使用此代码。干杯

参考: https ://github.com/angular/angular.js/issues/9607

于 2015-01-14T08:35:15.613 回答
3

嗨,即使已经两年了,对于搜索这个答案的人来说,只需使用 window.location.assign('/login')。这对我有用。

于 2016-09-09T04:19:55.427 回答