Использование $routeProvider для перенаправления на маршруты за пределами Angular

Я написал часть веб-приложения в Angular. Чтобы гарантировать, что все маршруты охвачены, я хотел добавить свойство redirectTo в $routeProvider, так что неверные маршруты будут возвращены в корень веб-приложения, которое не использует Angular.

Я пробовал:

$routeProvider.otherwise({
    redirectTo: '/'
});

но, очевидно, это только маршруты в Angular контролируемой части URL-адреса, поэтому пользователи будут перенаправлены на URL-адрес, например http://app.com/angular-part-of-web-app#, вместо http://app.com, где я бы хотел, чтобы они ушли.

Я работал над этим, имея пустую часть, чтобы действовать как страница "404", а затем контроллер, который просто использует объект $window для перенаправления на нужную страницу:

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

Однако это означает, что "слишком шумные, должно быть лучше" сигнальные колокола. Есть ли лучший способ сделать это в Angular?

EDIT: Angular маршруты - перенаправление на внешний сайт? не дали ответа на тот же вопрос. Я собираюсь оставить свой вопрос открытым, вместо того, чтобы пометить его как дубликат (пока), так как мир Angular перемещается так быстро, предыдущий ответ больше не может быть.

Ответ 1

Вышеупомянутое решение с /404 не работает для меня. Это, однако, работает

.otherwise({
    controller : function(){
        window.location.replace('/');
    }, 
    template : "<div></div>"
});

PS. Я использую Angular 1.2.10

Ответ 2

Вы можете сделать что-то вроде этого:

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

Это по сути то же самое, только он использует меньше кода.

Ответ 3

Не уверен, какая версия Angular JS была принята в качестве ответа, но свойство redirectTo принимает функцию. Итак, почему бы не сделать что-то более простое:

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

Очевидно, вам нужно создать свой собственный файл 404.html. Или где бы ни находилась ваша страница 404.

Ответ 4

Ни один из ответов, включая отмеченный ответ, не работал у меня. Я считаю, что мое решение также решает вашу проблему, и я бы поделился своим прецедентом, а также ссылкой для будущих читателей.

Проблема с использованием метода маршрутного контроллера: Когда контроллер загружен, маршрутизация уже получила доступ к состояниям API истории для меня (я использую режим HTML5, не уверен, влияет ли это на не-HTML5-режим).

В результате, хотя я могу перенаправить людей на правильную страницу, используя   window.location.replace( '/');, если пользователь затем нажимает "Назад" в своем браузере, он переходит в неправильное состояние.

Сценарий: Мы реализуем многостраничную модель, и у меня есть модуль моей админ-страницы отдельно от модулей моей домашней страницы (не-администратора). У меня есть $location.path('/') где-то в одном из моего контроллера администратора, но поскольку домашняя страница не упакована в модуль страницы администратора, я хочу принудительно перезагрузить всю страницу, когда обнаруживаю маршрут '/'.

Решение: Нам нужно перехватить $routeChangeStart, прежде чем ngRoute обратится к любой информации о состоянии. Таким образом, мы можем даже указать внешний href, передав url для redirectTo param в $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;
        });
      }
    });
  }
]);

Пожалуйста, предоставьте любую обратную связь, поскольку я буду использовать этот код сам. Приветствия

Справка: https://github.com/angular/angular.js/issues/9607

Ответ 5

Привет, хотя прошло уже два года, только для тех, кто ищет этот ответ, просто используйте window.location.assign('/login'). Это работает для меня.