ui-router 1.x.x在解析期间更改$ transition $ .params()

时间:2018-02-14 10:37:36

标签: angularjs angular-ui-router

尝试迁移angularjs应用程序以使用新版本的angular-ui-router 1.0.14,并在尝试在解决状态时更改$stateParams时偶然发现问题。

例如,之前(使用angular-ui-router 0.3.2时)修改$stateParams的工作方式如下:

 $stateProvider.state('myState', {
   parent: 'baseState',
   url: '/calendar?firstAvailableDate',
   template: 'calendar.html',
   controller: 'CalendarController',
   controllerAs: 'calendarCtrl',
   resolve: {
     availableDates: ['CalendarService', '$stateParams', function(CalendarService, $stateParams) {
       return CalendarService.getAvailableDates().then(function(response){
          $stateParams.firstAvailableDate = response[0];
          return response;
       });
     }]
   }
 })

问题是{1}}在解决后填充,我不知道如何在解析期间更新firstAvailableDate时使用新版$transition$.params() 1.0.14。

我尝试过,并设法用

更新url参数
  1. 触发angular-ui-router但这会重新加载状态,因此屏幕闪烁

  2. 修改$state.go('myState', {firstAvailableDate : response[0]})以实际覆盖参数。在查看$transition$.treeChanges().to[$transition$.treeChanges().length-1].paramValues.firstAvailableDate = response[0]; params()上的实施后,我已经完成了这项工作。

  3. 尽管这些选项都有效,但它们似乎是黑客而不是书籍实施。

    尝试修改解析中的参数时使用的正确方法是什么?

1 个答案:

答案 0 :(得分:4)

使用动态参数的方法:

请查看此文档:params.paramdeclaration#dynamic。也许这就是你要找的东西:...a transition still occurs...

  

当dynamic为true时,更改参数值不会导致输入/退出状态。不会重新获取结算,也不会重新加载视图。

     

通常,如果参数值发生变化,则声明将重新加载(输入/退出)参数的状态。当参数是动态的时,仍然会发生转换,但它不会导致状态退出/进入。

     

这可以用于构建UI,其中组件在param值更改时自动更新。这很有用的常见场景是搜索/分页/排序。

注意您无法在$stateProvider.state内将此类逻辑纳入您的决心。我会通过使用dynamic参数来防止状态重新加载。遗憾的是,当您尝试在解析部分内更新状态(例如,使用dynamic)时,$stage.go()规则不起作用。因此,我将该逻辑移动到控制器中以使其工作得很好 - DEMO PLNKR

由于userId是动态参数,因此视图在更改时不会再次进入/退出。

定义动态参数:

  $stateProvider.state('userlist.detail', {
    url: '/:userId',
    controller: 'userDetail',
    controllerAs: '$ctrl',
    params: {
      userId: {
        value: '',
        dynamic: true
      }
    },
    template: `
        <h3>User {{ $ctrl.user.id }}</h3>

        <h2>{{ $ctrl.user.name }} {{ !$ctrl.user.active ? "(Deactivated)" : "" }}</h2>

        <table>
          <tr><td>Address</td><td>{{ $ctrl.user.address }}</td></tr>
          <tr><td>Phone</td><td>{{ $ctrl.user.phone }}</td></tr>
          <tr><td>Email</td><td>{{ $ctrl.user.email }}</td></tr>
          <tr><td>Company</td><td>{{ $ctrl.user.company }}</td></tr>
          <tr><td>Age</td><td>{{ $ctrl.user.age }}</td></tr>
        </table>
    `
  });

您的控制器:

app.controller('userDetail', function ($transition$, $state, UserService, users) {

  let $ctrl = this;

  this.uiOnParamsChanged = (newParams) => {

    console.log(newParams);

    if (newParams.userId !== '') {
      $ctrl.user = users.find(user => user.id == newParams.userId);
    }
  };

  this.$onInit = function () {

    console.log($transition$.params());

    if ($transition$.params().userId === '') {
      UserService.list().then(function (result) {
        $state.go('userlist.detail', {userId: result[0].id});
      });
    }
  }
});

在路线更改开始时使用$transition.on*挂钩处理新的参数:

另一种方法是在更改状态之前设置正确的state参数。但你已经说过,这是你不想要的。如果我遇到同样的问题:在更改视图之前,我会尝试设置正确的state参数。

app.run(function (
    $transitions,
    $state,
    CalendarService
) {

    $transitions.onStart({}, function(transition) {
        if (transition.to().name === 'mySate' && transition.params().firstAvailableDate === '') {

            // please check this, I don't know if a "abort" is necessary
            transition.abort();

            return CalendarService.getAvailableDates().then(function(response){
                // Since firstAvailableDate is dynamic 
                // it should be handled as descript in the documents.
                return $state.target('mySate', {firstAvailableDate : response[0]});
            });
        }
    });
});

通过redirectTo

开始路线更改时使用$transition.on*挂钩处理新的参数
  

注意:在LAZY结算之前,redirectTo被处理为onStart挂钩。

这与标题“通过在路线更改开始时使用$transition.on*挂钩处理新的参数”附近提供的内容相同,因为redirectTo也是{{1自动处理的钩子。

onStart