UI路由器:如何自动从无效状态重定向

时间:2016-04-05 13:19:35

标签: angularjs angular-ui-router

我正在以scotch.io的风格构建一个多步骤表单。我使用resolve来限制对下一步的访问,直到当前步骤的对象存在于服务模型上(侧点 - 是否有DRYer方法来执行此操作?)。

各州

以下是我的顶级路线:

angular
  .module('donate')
  .config(routerConfig);

/** @ngInject */
function routerConfig($stateProvider, $urlRouterProvider) {
  $stateProvider
    .state('root', {
      url: '',
      abstract: true,
      views: {
        'donate': {
          controller: 'DonateController as donate',
          templateUrl: 'app/components/donate/donate.html'
        },
        'stories': {
          controller: 'StoriesController as stories',
          templateUrl: 'app/components/stories/views/stories.html'
        }
      }
    });

  $urlRouterProvider.otherwise('/');
}

这些是相关的儿童路线。

angular
  .module('donate')
  .config(function($stateProvider) {
    $stateProvider
      .state('root.amount', {
        url: '/',
        controller: 'AmountController as amount',
        templateUrl: 'app/components/donate/views/amount.html'
      })
      .state('root.card', {
        url: '/card',
        resolve: {
          amount: function($q,DonateService){
            if(!DonateService.amount){
              var errorObject = {code:'NO_AMOUNT'};
              return $q.reject(errorObject);
            }
          }
        },
        controller: 'CardController as card',
        templateUrl: 'app/components/donate/views/card.html'
        })
      .state('root.billing', {
        url: '/billing-info',
        resolve: {
          card: function($q,DonateService){
            if(!DonateService.card){
              var errorObject = {code:'NO_CARD'};
              return $q.reject(errorObject);
            }
          }
        },
        controller: 'BillingController as billing',
        templateUrl: 'app/components/donate/views/billing.html'
        })
      .state('root.confirm', {
        url:'/confirm',
        resolve: {
          billing: function($q,DonateService){
            if(!DonateService.email){
              var errorObject = {code:'NO_BILLING_INFO'};
              return $q.reject(errorObject);
            }
          }
        },
        controller: 'ConfirmController as confirm',
        templateUrl: 'app/components/donate/views/confirm.html'
      })
      .state('root.success', {
        url:'/success',
        controller: 'SuccessController as success',
        templateUrl: 'app/components/donate/views/success.html'
      })
      .state('root.error', {
        url:'/error',
        controller: 'ErrorController as error',
        templateUrl: 'app/components/donate/views/error.html'
      });
  });

报告错误

父控制器上的此开关可防止用户在孩子拒绝上述承诺时单击步骤导航,跳转到下一步。

angular
  .module('donate')
  .controller('DonateController', DonateController);

DonateController.$inject = ['DonateService', '$rootScope', '$state', '$log'];

/* @ngInject */
function DonateController(DonateService, $rootScope, $state, $log) {
  var vm = this;
  vm.DonateService = DonateService;

  $rootScope.$on('$stateChangeError', stateError);

  function stateError (e, toState, toParams, fromState, fromParams, error) {
    switch (error.code) {
      case 'NO_AMOUNT':
        $log.debug('State Error:', error.code);
        $state.go('root.amount');
        break;
      case 'NO_CARD':
        $log.debug('State Error:', error.code);
        $state.go('root.card');
        break;
      case 'NO_BILLING_INFO':
        $log.debug('State Error:', error.code);
        $state.go('root.billing');
        break;
      default:
        $log.debug('State Error:', error.code);
        $state.get('error').error = error;
        $state.go('root.amount');
    }
  }
}

问题

这很有效。当用户试图点击无法访问的步骤的导航丸时,控制台会尽职地发出错误消息或三个错误消息。但仍然存在一个问题:用户可以浏览(通过URL栏)到/ card,/ billing-info和/ confirm,他们会看到一个空白视图,没有控制台输出可以说。

如何将其挂钩,以便浏览到他们不应该使用的任何路径的用户被弹回到开头(或者更好,最后完成的状态)?

1 个答案:

答案 0 :(得分:0)

$rootScope.$on()移至runBlock解决了问题。