使用UI-Router将用户转换为子状态时将其定向到子状态


77

考虑以下:

.state('manager.staffList', {url:'^/staff?alpha', templateUrl: 'views/staff.list.html', data:{activeMenu: 'staff'}, controller: 'staffListCtrl'})
.state('manager.staffDetail', {url:'^/staff/{id}' , templateUrl: 'views/staff.html', data:{activeMenu: 'staff'}, controller: 'staffDetailsCtrl'})
  .state('manager.staffDetail.view', {url:'/view',  templateUrl: 'views/staff.details.html', data:{activeMenu: 'staff'}})
    .state('manager.staffDetail.view.schedule', {url:'/schedule', templateUrl:'views/staff.view.schedule.html', data:{activeMenu: 'staff'}})
    .state('manager.staffDetail.view.history', {url:'/history' , templateUrl:'views/staff.view.history.html', data:{activeMenu: 'staff'}})
    .state('manager.staffDetail.view.log', {url:'/log', templateUrl:'views/staff.view.log.html', data:{activeMenu: 'staff'}})
    .state('manager.staffDetail.view.files', {url:'/files', templateUrl:'views/staff.view.files.html', data:{activeMenu: 'staff'}})
  .state('manager.staffDetail.edit', {url:'/edit',  templateUrl: 'views/staff.edit.html', data:{activeMenu: 'staff'}})

如果转到domain.com/staff/1234/view,我如何默认为manager.staffDetail.view.schedule子状态?


仅供参考,我目前使用的redirectTo方法在这里找到stackoverflow.com/questions/29491079/...
米克尔

请不要编辑此代码以创建更多垂直代码。该代码经过专门格式化,可以直观地显示与父母相比的孩子状态。
Meeker

@UdayHiwarale与上面已经发布的链接相同
Meeker

我的错。我没看到。
Uday Hiwarale '16

Answers:


136
  1. 首先,将属性添加到的'manager.staffDetail.view'状态abstract:true。这不是必需的,但是您要设置它,因为您永远不会直接进入此状态,因此总是会进入其子状态之一。

  2. 然后执行以下操作之一

    • 'manager.staffDetail.view.schedule'州提供一个空URL。这将使其与父状态URL匹配相同的URL,因为它不会在父URL后面附加任何内容。

      .state('manager.staffDetail.view.schedule', {url:'', ...

    • 或者,如果您想保持默认子路由的网址不变,请在module.config中设置重定向。此处的代码会将的任何位置重定向'/staff/{id}/view'到的位置'/staff/{id}/view/schedule'

      $urlRouterProvider.when('/staff/{id}/view', '/staff/{id}/view/schedule');


4
对于$urlRouterProvider重定向,使用带有的链接时出现错误ui-sref="manager.staffDetail.view",因此我需要abstract: true从父状态声明中删除。
Colllin 2014年

4
第二个选项对内部ui-sref链接不起作用(它不会进入子状态)
Stepan Suvorov 2014年

20

要设置默认的子视图,请检查此示例。单击时Route 1加载默认状态route1.list

// For any unmatched url, send to /route1
$stateProvider
  .state('route1', {
      url: "/route1",
      abstract:true ,
      templateUrl: "route1.html"
  })
  .state('route1.list', {
      url: '',
      templateUrl: "route1.list.html",
      controller: function($scope){
        $scope.items = ["A", "List", "Of", "Items"];
      }
  })
  .state('route1.desc', {
      url: "/desc",
      templateUrl: "route1.desc.html",
      controller: function($scope){
        $scope.items = [];
      }
  })
  .state('route2', {
    url: "/route2",
    templateUrl: "route2.html"
  })
  .state('route2.list', {
    url: "/list",
    templateUrl: "route2.list.html",
    controller: function($scope){
      $scope.things = ["A", "Set", "Of", "Things"];
    }
  })

如果route1.desc没有url,您仍然可以使用来访问它$state.go,但是route1.list默认情况下会在/route1:)上加载它:如果您不想通过url直接访问该状态,这将非常有用
Andrei Cojea 2015年

2
如果我们想在ui-sref中使用父州,就会有一个大问题
Kishore Relangi

您必须使用href =“ / abstractroute”链接到父级
Eric Shell

谁能向我解释为什么route1此示例中的状态需要templateUrl?或更笼统地说,为什么一个abstract:true州需要模板?
授予

非常感谢你。
Brynner Ferreira

8

我遇到了同样的问题,发现此解决方案有效:

https://github.com/angular-ui/ui-router/issues/948#issuecomment-75342784

引用自@christopherthielen在github上

“目前,不要声明您的状态摘要,而使用以下配方:”

 app.run($rootScope, $state) {
    $rootScope.$on('$stateChangeStart', function(evt, to, params) {
      if (to.redirectTo) {
        evt.preventDefault();
        $state.go(to.redirectTo, params)
      }
    });
  }

  $stateProvider.state('parent' , {
      url: "/parent",
      templateUrl: "parent.html",
      redirectTo: 'parent.child'
  });

  $stateProvider.state('parent.child' , {
      url: "/child",
      templateUrl: "child.html"
  });

以下是该流程的工作原理:

  1. 用户导航到状态“父母”
  2. “ $ stateChangeStart”事件被触发
  3. “ $ stateChangeStart”的侦听器捕获事件并将“ toState”(即“父”)和“ event”传递给处理函数
  4. 处理函数检查“ toState”上是否设置了“ redirectTo”。
  5. 如果未设置“ redirectTo”,则什么也没有发生,并且用户继续进入“ toState”状态。
  6. 如果设置了“ redirectTo”,则事件被取消(event.preventDefault),并且$ state.go(toState.redirectTo)将其发送到“ redirectTo”(即“ parent.child”)中指定的状态。
  7. “ $ stateChangeStart”事件再次被触发,但是这次“ toState” ==“ parent.child”并且未设置“ redirectTo”选项,因此它继续执行“ toState”。

谁能解释这个。这不会成为无限循环吗?
Kishore Relangi 2015年

嗨Kishore-我更新了答案以解释其工作原理。除非您在“ redirectTo”选项中明确指定“父”状态,否则不会有无限循环。
Chuck D

我尝试了这个,但不幸的是,这对我不起作用。我正在使用ui路由器v0.3.1
侯赛因

7

很晚了,但我认为您可以“重定向”到您想要的状态。

.state('manager.staffDetail.view', {
    url:'/view',
    templateUrl: 'views/staff.details.html',
    controller: 'YourController'
})

app.controller('YourController', ['$state',
function($state) {
    $state.go('manager.staffDetail.view.schedule');
}]);

您可以简短地在状态配置中编写控制器。


3
我试过了,但是它将加倍负载控制器,解析度以及所有onStateChange。我只是使用$ urlRouterProvider.when('/ app / service','/ app / service / list')来整理
Meeker 2014年

它将仅加载两次或无限次,因为子状态还会再次调用父状态,因为我们将再次重定向到子状态。
Kishore Relangi 2015年

如果您的导航具有父ref,则它将在后续点击中不起作用-仅在初始控制器加载时起作用。
乔纳森·希尔

3

我将'manager.staffDetial.view'更改为抽象状态,并将默认子状态的网址留空''

// Staff
.state('manager.staffList',    {url:'^/staff?alpha',      templateUrl: 'views/staff.list.html', data:{activeMenu: 'staff'}, controller: 'staffListCtrl'})
.state('manager.staffDetail',   {url:'^/staff/{id}', templateUrl: 'views/staff.html', data:{activeMenu: 'staff'}, controller: 'staffDetailsCtrl'})
.state('manager.staffDetail.view',   {url:'/view', abstract: true, templateUrl: 'views/staff.details.html', data:{activeMenu: 'staff'}})
    .state('manager.staffDetail.view.schedule', {url:'', templateUrl:'views/staff.view.schedule.html', data:{activeMenu: 'staff'}})
    .state('manager.staffDetail.view.history', {url:'/history', templateUrl:'views/staff.view.history.html', data:{activeMenu: 'staff'}})
    .state('manager.staffDetail.view.log', {url:'/log', templateUrl:'views/staff.view.log.html', data:{activeMenu: 'staff'}})
    .state('manager.staffDetail.view.files', {url:'/files', templateUrl:'views/staff.view.files.html', data:{activeMenu: 'staff'}})
.state('manager.staffDetail.edit',   {url:'/edit',  templateUrl: 'views/staff.edit.html', data:{activeMenu: 'staff'}})

13
所以您基本上完全按照我的建议做了...为什么不给我答案正确的对勾呢?这样我就可以获得代表点。
Tim Kindberg

我不确定您是否知道“完全”一词的含义。但是,您的代码示例使用routeProvider方法。我选择完全不使用它,而是将解决方案保留在状态管理器中。这样,代码将保持干净,并且不会添加任何不必要的额外代码行。您的示例是一个可能的答案,但不是最可接受的答案。
米克(Meeker)2013年

我已经提到过,似乎您所做的一切(不过,是的,在我的示例中的代码是不必要的)。我:“ ...您应该将其设置为抽象状态。” 您:“我将'manager.staffDetial.view'更改为抽象状态...” ME:“或者,另一个选择是给日程表提供一个空URL。” 您:“ ...并将我的默认子状态的网址留空”。严重的是,没有难过的感觉,我很高兴您知道了。
蒂姆·金伯格

1
抱歉,您的答案令人困惑,而且没有重点。阅读您的解释后,我看到您提供了单独的选项,最后,如果我将您的第一个选项和最后一个选项进行了某种组合,而忽略了中间的建议,我将有一个解决方案。我想我知道你要去哪里,但是如果我将你的答案标记为答案,我不确定这对下一个读者是否有帮助。如果您想编辑答案并整理答案,我们很乐意为您提供答案。
Meeker

是的,您是对的,我通过电话写了答案...:PI已整理好答案,希望现在更有意义。此外,我注意到,在谷歌,如果我搜索UI路由器这个线程是第四个结果,所以它重要的是我们拥有它很清楚。
蒂姆·金伯格

1

在“ angular-ui-router”:“ 0.2.13”中,我认为@nfiniteloop的重定向解决方案不起作用。一旦我回滚到0.2.12(并且可能不得不将$ urlRouterProvider.when放在$ stateProvider之前)时,它就起作用了。

参见https://stackoverflow.com/a/26285671/1098564

https://stackoverflow.com/a/27131114/1098564获得解决方法(如果您不想回到0.2.12)

截至2014年11月28日,https://github.com/angular-ui/ui-router/issues/1584指示它应在0.2.14中重新工作


1

这已经很晚了,但是这里所有的答案都不适用于AngularJS的最新版本的angular-ui-router。从版本开始(特别是@ uirouter / angularjs#v1.0.x,您可以仅输入redirectTo: 'childStateName'。的第二个参数,$stateProvider.state()例如:

$stateProvider
.state('parent', {
  resolve: {...},
  redirectTo: 'parent.defaultChild'
})
.state('parent.defaultChild', {...})

这是相关的文档部分:https : //ui-router.github.io/guide/ng1/migrate-to-1_0#state-hook-redirectto

希望这可以帮助某人!


0

这是一个非常简单和透明的替代方法,只需在ui路由器中修改父状态即可:

  .state('parent_state', {
    url: '/something/:param1/:param2',
    templateUrl: 'partials/something/parent_view.html',  // <- important
    controller: function($state, $stateParams){
      var params = angular.copy($state.params);
      if (params['param3'] === undefined) {
        params['param3'] = 'default_param3';
      }
      $state.go('parent_state.child', params) 
    }
  })

  .state('parent_state.child', {
    url: '/something/:param1/:param2/:param3',
    templateUrl: '....',  
    controller: '....'
  })

0

添加angular-ui-router-default并将abstractdefault选项添加到父状态:

...

.state('manager.staffDetail.view', {abstract: true, default: '.schedule', url:'/view',  templateUrl: 'views/staff.details.html', data:{activeMenu: 'staff'}})
  .state('manager.staffDetail.view.schedule', {url:'/schedule', templateUrl:'views/staff.view.schedule.html', data:{activeMenu: 'staff'}})

...

注意:要使其正常工作,父模板必须在其中<ui-view/>某处。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.