本文介绍了我可以在 onExit 中停止转换到下一个状态吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有两个状态,A 和 B.

  • 当我通过单击关闭按钮退出状态 A 时,我使用 $state.go 转换到屏幕 A 到状态 B(屏幕 B)
  • 当我通过点击屏幕 A 上的后退浏览器按钮退出状态 A 时,我会随着浏览器 URL 的变化转换到状态 B(屏幕 B)

在屏幕 A 的 onExit 中,我进行了检查,如果失败,则会打开一个错误对话框,单击错误对话框上的关闭会向 onExit 返回一个失败的承诺

然而 onExit 仍然继续,我去屏幕 B

如果 onExit 出现故障,是否可以停止从状态 A(屏幕 A)到状态 B(屏幕 B)的转换?

解决方案

您可以通过实施 $stateChangeStart 事件处理程序,您可以在其中在需要时取消状态转换 (event.preventDefault();).

下面是一个复选框模拟禁用转换条件的示例.在这种情况下,状态更改(state.go 和导航)会打开一个模态,要求用户接受/拒绝被阻止的转换(某些验证检查的另一个模拟):

var myApp = angular.module('myApp', ['ui.router','ui.bootstrap']);myApp.config(function($stateProvider, $urlRouterProvider) {$urlRouterProvider.otherwise('/state_a');$stateProvider.state('state_a', {网址:'/state_a',templateUrl: 'stateA.html',onEnter:函数(){console.log("onEnter stateA");},onExit:函数($rootScope,$state){console.log("onExit stateA:"+$rootScope.chk.transitionEnable);},控制器:函数($scope,$state){$scope.goToStateB = function() {$state.go("state_b");}}}).state('state_b', {网址:'/state_b',templateUrl: 'stateB.html',onEnter:函数(){console.log("onEnter stateB");},退出:函数(​​){console.log("onExit stateB");},控制器:功能($范围){}});});myApp.controller('mainCtrl', function($rootScope, $scope, $uibModal, $state) {$rootScope.chk = {};$rootScope.chk.transitionEnable = true;$rootScope.$on('$stateChangeStart',功能(事件,toState,toParams,fromState,fromParams,选项){如果(!$rootScope.chk.transitionEnable){event.preventDefault();$scope.toState = toState;$scope.open();} 别的 {console.log("$stateChangeStart: "+toState.name);}})$scope.open = 函数 () {var modalInstance = $uibModal.open({动画:$scope.animationsEnabled,templateUrl: 'myModal.html',范围:$范围,控制器:函数($uibModalInstance,$scope){$scope.ok = 函数 () {$uibModalInstance.close('ok');};$scope.cancel = 函数 () {$uibModalInstance.dismiss('cancel');};},尺寸:'sm'});modalInstance.result.then(函数(值){console.info('模态关闭:' + value);}, 功能 () {console.info('模态关闭');$rootScope.chk.transitionEnable = true;$state.go($scope.toState.name);});};});
<头><link href="//netdna.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="样式表"><script src="//ajax.googleapis.com/ajax/libs/angularjs/1.4.9/angular.js"></script><script src="//ajax.googleapis.com/ajax/libs/angularjs/1.4.9/angular-animate.js"></script><script src="//angular-ui.github.io/bootstrap/ui-bootstrap-tpls-1.1.1.js"></script><script src="//cdnjs.cloudflare.com/ajax/libs/angular-ui-router/0.2.17/angular-ui-router.min.js"></script><script src="app.js"></script><body ng-app="myApp" ng-controller="mainCtrl"><nav class="navbar navbar-inverse" role="navigation"><div class="navbar-header"><a class="navbar-brand" ui-sref="#">AngularUI Router</a>

<ul class="nav navbar-nav"><li><a ui-sref="state_a">状态A</a></li><li><a ui-sref="state_b">状态B</a></li></nav><div class="容器"><div ui-view></div>

<script type="text/ng-template" id="myModal.html"><div class="modal-header"><h3 class="modal-title">Title</h3>

<div class="modal-body">过渡到 <b>{{toState.name}}</b>被禁用,接受还是忽略?

<div class="modal-footer"><button class="btn btn-primary" type="button" ng-click="ok()">接受</button><button class="btn btn-warning" type="button" ng-click="cancel()">忽略</button>

<script type="text/ng-template" id="stateA.html"><div class="jumbotron text-center"><h1>状态A</h1><p>示例</p><a class="btn btn-primary" ng-click="goToStateB()">转到状态B</a><a class="btn btn-danger">什么都不做...</a>

<div class="checkbox"><标签><input type="checkbox" ng-model="chk.transitionEnable">启用过渡<pre>chk.transitionEnable = {{chk.transitionEnable}}</pre>

<script type="text/ng-template" id="stateB.html"><div class="jumbotron text-center"><h1>状态B</h1><p>页面...</p>

<div class="容器">布拉布拉<div class="checkbox"><标签><input type="checkbox" ng-model="chk.transitionEnable">启用过渡<pre>chk.transitionEnable = {{chk.transitionEnable}}</pre>

</html>

I have two states, A and B.

In the onExit of screen A I do a check and if this fails an Error Dialog opens, clicking Close on the error dialog returns a failed promise to the onExit

However the onExit still goes ahead and I go to screen B

Is it possible to stop the transition from State A (Screen A) to State B (Screen B) if something fails in the onExit?

解决方案

You can achieve your goal implementing a $stateChangeStart event handler in which you can cancel the state transition (event.preventDefault();) when needed.

Here below is an example where a checkBox simulate a condition of transition disabled. In this case on state change (both state.go and navigation) it opens a modal asking the user to accept/reject the transition blocked (another simulation of some validation check):

var myApp = angular.module('myApp', ['ui.router','ui.bootstrap']);

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

  $urlRouterProvider.otherwise('/state_a');

  $stateProvider
    .state('state_a', {
      url: '/state_a',
      templateUrl: 'stateA.html',
      onEnter: function() {
        console.log("onEnter stateA");
      },
      onExit: function($rootScope, $state) {
        console.log("onExit stateA: "+$rootScope.chk.transitionEnable);
        
      },
      controller: function($scope, $state) {
        $scope.goToStateB = function() {
          $state.go("state_b");
        }
      }
    })
    .state('state_b', {
      url: '/state_b',
      templateUrl: 'stateB.html',
      onEnter: function() {
        console.log("onEnter stateB");
      },
      onExit: function() {
        console.log("onExit stateB");
      },
      controller: function($scope) {
        
      }
    });

});

myApp.controller('mainCtrl', function($rootScope, $scope, $uibModal, $state) {

  $rootScope.chk = {};
  $rootScope.chk.transitionEnable = true;
  
  $rootScope.$on('$stateChangeStart',
    function(event, toState, toParams, fromState, fromParams, options) {
      if (!$rootScope.chk.transitionEnable) {
        event.preventDefault();
        $scope.toState = toState;
        $scope.open();
      } else {
        console.log("$stateChangeStart: "+toState.name);
      }
  })
  
  $scope.open = function () {

    var modalInstance = $uibModal.open({
      animation: $scope.animationsEnabled,
      templateUrl: 'myModal.html',
      scope: $scope,
      controller: function($uibModalInstance, $scope) {
          $scope.ok = function () {
            $uibModalInstance.close('ok');
          };
        
          $scope.cancel = function () {
            $uibModalInstance.dismiss('cancel');
          };
      },
      size: 'sm'
    });

    modalInstance.result.then(function (value) {
      console.info('Modal closed: ' + value);
        
    }, function () {
      console.info('Modal dismissed');
      $rootScope.chk.transitionEnable = true;
      $state.go($scope.toState.name);
    });
  };

});
<!DOCTYPE html>
<html>

<head>
  <link href="//netdna.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet">
  <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.4.9/angular.js"></script>
  <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.4.9/angular-animate.js"></script>
  <script src="//angular-ui.github.io/bootstrap/ui-bootstrap-tpls-1.1.1.js"></script>
  <script src="//cdnjs.cloudflare.com/ajax/libs/angular-ui-router/0.2.17/angular-ui-router.min.js"></script>
  <script src="app.js"></script>
</head>

<body ng-app="myApp" ng-controller="mainCtrl">

  <nav class="navbar navbar-inverse" role="navigation">
    <div class="navbar-header">
      <a class="navbar-brand" ui-sref="#">AngularUI Router</a>
    </div>
    <ul class="nav navbar-nav">
      <li><a ui-sref="state_a">State A</a></li>
      <li><a ui-sref="state_b">State B</a></li>
    </ul>
  </nav>

  <div class="container">
    <div ui-view></div>
  </div>

  <script type="text/ng-template" id="myModal.html">
    <div class="modal-header">
      <h3 class="modal-title">Title</h3>
    </div>
    <div class="modal-body">
      Transition to <b>{{toState.name}}</b> is disabled, accept or ignore?
    </div>
    <div class="modal-footer">
      <button class="btn btn-primary" type="button" ng-click="ok()">Accept</button>
      <button class="btn btn-warning" type="button" ng-click="cancel()">Ignore</button>
    </div>
  </script>
 
  <script type="text/ng-template" id="stateA.html">
  <div class="jumbotron text-center">
    <h1>state A</h1>
    <p>Example</p>
    
    <a class="btn btn-primary" ng-click="goToStateB()">Goto State B</a>
    <a class="btn btn-danger">Do nothing...</a>
  </div>
  <div class="checkbox">
    <label>
      <input type="checkbox" ng-model="chk.transitionEnable"> Enable transition
    </label>
    <pre>chk.transitionEnable = {{chk.transitionEnable}}</pre>
  </div>
  </script>
  
  <script type="text/ng-template" id="stateB.html">
<div class="jumbotron text-center">
    <h1>state B</h1>
    <p>The page... </p>
</div>

<div class="container">
    Bla bla
  <div class="checkbox">
    <label>
      <input type="checkbox" ng-model="chk.transitionEnable"> Enable transition
    </label>
    <pre>chk.transitionEnable = {{chk.transitionEnable}}</pre>
  </div>
</div>
  </script>

</body>

</html>

这篇关于我可以在 onExit 中停止转换到下一个状态吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-30 11:19