UI 路由器:如何从无效状态自动重定向 [英] UI Router: how to automatically redirect from invalid state

查看:25
本文介绍了UI 路由器:如何从无效状态自动重定向的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在构建一个 scotch 风格的多步表单.io.我使用了 resolve 来限制对后续步骤的访问,直到当前步骤的对象存在于服务模型中(侧面 - 是否有 DRYer 方法来做到这一点?).

I'm building a multistep form in the style of scotch.io. I used resolve to restrict access to next steps until the current step's object exists on the service model (side point – is there a DRYer way to do this?).

这是我的顶级路线:

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

一点错误报告

父控制器上的这个开关可以防止用户在孩子拒绝上面设置的承诺时通过点击步骤导航跳转到下一步.

A little bit of error reporting

This switch on the parent controller prevents users from jumping to the next step by clicking on the step nav when the the children's reject the promise set up above.

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,他们将看到一个空白视图,没有控制台输出可言.

The Question

This works swimmingly. When a user tries to click on an inaccessible step's nav pill, the console dutifully belches out an error message or three. But one problem remains: Users can browse (via the URL bar) to /card, /billing-info and /confirm and they'll be greeted with a blank view, with no console output to speak of.

我如何挂钩它,以便浏览到他们不应该在的任何路线的用户被退回到开头(或者更好的是,最后完成的状态)?

How do I hook it so that users who browse to any route they aren't supposed to be on are bounced back to the beginning (or, even better, the last completed state)?

推荐答案

$rootScope.$on() 移动到 runBlock 解决了问题.

Moving $rootScope.$on() to the runBlock solved the problem.

这篇关于UI 路由器:如何从无效状态自动重定向的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆