2015-02-05 42 views
4

這裏是我迄今爲止與UI路由器的狀態:防止打孩子指出UI路由器

$stateProvider 
    .state('tools', { 
    url: '/tools/:tool', 
    template: '<div ui-view=""></div>', 
    abstract: true, 
    onEnter: function ($stateParams, $state, TOOL_TYPES) { 
     if (TOOL_TYPES.indexOf($stateParams.tool) === -1) { 
     $state.go('error'); 
     } 
    } 
    }) 
    .state('tools.list', { 
    url: '', 
    templateUrl: 'app/tools/tools.tpl.html', 
    controller: 'ToolsController' 
    }) 
    .state('tools.view', { 
    url: '/:id/view', 
    templateUrl: 'app/tools/partials/tool.tpl.html', 
    controller: 'ToolController' 
    }); 

正如你可以看到雙親狀態有參數tool這隻能是在TOOL_TYPES陣列。因此,如果tool不可用,我想重定向到錯誤頁面。

其實,一切正常,但我得到兩個錯誤:

TypeError: Cannot read property '@' of null

TypeError: Cannot read property '@tools' of null

,所以我想,孩子的狀態一直在 '打' 反正。是否有可能防止這種情況發生?或者也許有其他方法可以實現我想要的?

+0

我覺得這可能是一個已知的問題與UI的路由器。檢查這個:https://github.com/angular-ui/ui-router/issues/1434和這個:https://github.com/angular-ui/ui-router/issues/1234了。 – 2015-02-05 15:53:55

回答

9

Angular ui-router's文檔中提到,當一個國家變得活躍,因此,孩子的狀態被激活onEnter回調被調用。

爲了解決這個問題,你需要實現兩件事情:

  1. 創建resolve返回一個拒絕承諾一旦特定條件並不適用於該狀態。確保被拒絕的承諾傳遞有關重定向狀態的信息。

  2. $rootScope中創建一個$stateChangeError事件處理函數,並使用第6個參數表示您在拒絕的承諾中傳遞的信息。使用這些信息來創建您的重定向實現。

DEMO

的Javascript

angular.module('app', ['ui.router']) 

    .value('TOOL_TYPES', [ 
    'tool1', 'tool2', 'tool3' 
    ]) 

    .config(function($stateProvider, $urlRouterProvider) { 

    $stateProvider 

     .state('error', { 
     url: '/error', 
     template: 'Error!' 
     }) 

     .state('tools', { 
     url: '/tools/:tool', 
     abstract: true, 
     template: '<ui-view></ui-view>', 
     resolve: { 
      tool_type: function($state, $q, $stateParams, TOOL_TYPES) { 

      var index = TOOL_TYPES.indexOf($stateParams.tool); 

      if(index === -1) { 
       return $q.reject({ 
       state: 'error' 
       }); 
      } 

      return TOOL_TYPES[index]; 
      } 
     } 
     }) 

     .state('tools.list', { 
     url: '', 
     template: 'List of Tools', 
     controller: 'ToolsController' 
     }) 
     .state('tools.view', { 
     url: '/:id/view', 
     template: 'Tool View', 
     controller: 'ToolController' 
     }); 

    }) 

    .run(function($rootScope, $state) { 
    $rootScope.$on('$stateChangeError', function(
     event, toState, toStateParams, 
     fromState, fromStateParams, error) { 

     if(error && error.state) { 
      $state.go(error.state, error.params, error.options); 
     } 

    }); 
    }) 

    .controller('ToolsController', function() {}) 
    .controller('ToolController', function() {}); 
+0

謝謝@ryeballar,你的答案解決了這個問題。 – UngaBunga 2015-02-06 08:03:46