如何实现“ui-sref”被有条件地执行?

我想在浏览器跟踪由ui-routerdynamic创build的链接之前validation一定的条件。

我正在寻找$rootscope.$on('$stateChangeStart', ..)但我没有访问controller.$scope从那里。 我也需要在应用程序的几个地方使用它,并且会很麻烦。

请记住, ui-srefui-sref-active (一起工作)相关联,所以我不能删除ui-sref并且使用$state.$go('some-state')ng-click调用函数。

条件应该在$scope function和on on-click event进行评估(在能够取消它的转换之前)

我需要这样的东西:

 <li ui-sref-active="active"> <a ui-sref="somestate" ui-sref-if="model.validate()">Go Somestate</a> </li> 

我试过了:

 <li ui-sref-active="active"> <a ui-sref="somestate" ng-click="$event.preventDefault()">Go Somestate</a> </li> <li ui-sref-active="active"> <a ui-sref="somestate" ng-click="$event.stopImmediatePropagation()">Go Somestate</a> </li> 

 <li ui-sref-active="active"> <a ui-sref="somestate"> <span ng-click="$event.stopPropagation();">Go Somestate</span> </a> </li> 

甚至

 <li ui-sref-active="active"> <a ui-sref="somestate" onclick="return false;">Go Somestate</a> </li> 

但是不行。

SANDBOX

这个答案启发了我创build了一个指令,允许我打断最终改变状态的事件链。 为了方便和其他用途,还可以防止在同一个元素上执行ng-click。

JavaScript的

 module.directive('eatClickIf', ['$parse', '$rootScope', function($parse, $rootScope) { return { // this ensure eatClickIf be compiled before ngClick priority: 100, restrict: 'A', compile: function($element, attr) { var fn = $parse(attr.eatClickIf); return { pre: function link(scope, element) { var eventName = 'click'; element.on(eventName, function(event) { var callback = function() { if (fn(scope, {$event: event})) { // prevents ng-click to be executed event.stopImmediatePropagation(); // prevents href event.preventDefault(); return false; } }; if ($rootScope.$$phase) { scope.$evalAsync(callback); } else { scope.$apply(callback); } }); }, post: function() {} } } } } ]); 

HTML

 <li ui-sref-active="active"> <a ui-sref="somestate" eat-click-if="!model.isValid()">Go Somestate</a> </li> 

PLUNKER

你可以使用一个范围函数来返回:

  • 没有状态
  • 一个现有的状态

    像这样:

HTML:

 <li ui-sref-active="active"> <a ui-sref="{{checkCondition()}}">Go Somestate</a> </li> 

JS范围:

 $scope.checkCondition = function() { return model.validate() ? 'someState' : '-' // hack: must return a non-empty string to prevent JS console error } 

只有当函数返回一个现有的状态string时才会创buildhref属性。

或者,你可以做一个(丑):

 <li ui-sref-active="active"> <a ui-sref="somestate" ng-if="model.validate()">Go Somestate</a> <span ng-if="!model.validate()">Go Somestate</span> </li> 

希望这可以帮助

你总是可以在元素上加倍,并有条件地显示/隐藏

  <li ui-sref-active="active"> <a ng-show="condition1" style="color: grey">Start</a> <a ng-hide="condition1" ui-sref="start">Start</a> </li> 

http://plnkr.co/edit/ts4yGW?p=preview

有条件地实现路由而不修改指令,范围等最简单的解决方法是我在这里find的解决方法 – https://github.com/angular-ui/ui-router/issues/1489

<a ui-sref="{{condition ? '.childState' : '.'}}"> Conditional Link </a>

基于如何dynamic设置ui-sref值的答案,您可以在您的作用域中创build一个函数来构buildURL:

 $scope.buildUrl = function() { return $state.href('somestate', {someParam: 'someValue}); }; 

然后有条件地将它追加到与ng-href的链接

 <a ng-href="{{ someCondition ? buildUrl() : undefined }}">Link</a> 

正如你在下面的演示中看到的那样,如果值为负, ng-href不会添加href属性。

 angular.module('app', []) 
 <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script> <div ng-app="app"> <a ng-href="{{ condition ? 'http://thecatapi.com/apihttp://img.dovov.comget?format=src&type=gif' : undefined}}">This is the link</a> <br> <label for="checkbox"> <input type="checkbox" id="checkbox" ng-model="condition"> Link active? </label> </div> 

无需复杂的指令或黑客。 以下工作正常,并允许在非sref项目的点击具体处理:

 <a ng-repeat="item in items" ui-sref="{{item.sref || '-'}}" ng-click="$ctrl.click(item, $event)" >...</a> 

而在控制器中,一个简单的点击处理程序的项目没有item.sref

 this.click = function(item, event) { if (!item.sref) { event.preventDefault(); //do something else } }; 

我知道这是一个古老的问题,但为了将来的参考,我想提供一个替代解决scheme,因为我没有看到它的任何答案到目前为止。

期望:

 <li ui-sref-active="active"> <a ui-sref="somestate" ui-sref-if="model.validate()">Go Somestate</a> </li> 

潜在解决scheme (模板):

 <li ng-class="{ active: state.current.name === 'somestate' }"> <a ng-click="navigateToState()">Go Somestate</a> </li> 

而在控制器中:

 $scope.state = $state; $scope.navigateToState = navigateToState; function navigateToState() { if ($scope.model.valid) { $state.go('somestate'); } } 

对于那些仍然需要ng-click ui-sref组件或其父项的用户,可能的解决scheme。

我的解决scheme是使用href而不是ui-sref并修改Emanuel的指令,以便能够单独停止hrefng-click调用。

Planker 。

虽然它有一些限制:

  • 将不会使用ui-sref
  • 由于之前的限制,您应该为每个州制定不同的url
  • ui-sref-active也不起作用