如何实现有条件地执行“ui-sref”?
Posted
技术标签:
【中文标题】如何实现有条件地执行“ui-sref”?【英文标题】:How to achieve that "ui-sref" be conditionally executed? 【发布时间】:2014-10-25 08:12:50 【问题描述】:我想在浏览器跟随 ui-router 动态创建的链接之前验证某些条件。
我正在调查$rootscope.$on('$stateChangeStart', ..)
,但我无法从那里访问controller.$scope
。我还需要在应用程序的几个地方使用它,并且会很麻烦。
请记住,ui-sref
链接到 ui-sref-active
(一起工作),所以我不能删除 ui-sref
,也就是说,在使用 ng-click
调用的函数中使用 $state.$go('some-state')
。
应在$scope function
和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
【问题讨论】:
基本上你想在用户访问该链接时测试某个条件,然后决定他是否可以继续访问该链接? 是的,但在应用程序级别存在状态更改。链接不是字面意思。需要这样我才能防止它发生。 【参考方案1】:这个answer 启发了我创建一个指令,允许我中断最终改变状态的事件链。为了方便和其他用途,还可以防止对同一元素执行 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
【讨论】:
他们应该真正包含这个功能。它可以重命名为ui-sref-disable
。考虑打开一个拉取请求,@OneWay!
这太棒了。感谢这个花絮。我同意@DesignerGuy,应该是ui-sref-disabled
@DesignerGuy ...我们做到了,这就是他们回答我们要做的事情:复制这个模块:-D :-D :-D ----这里是链接---- > github.com/angular-ui/ui-router/issues/…
这是一种解决方法。有更简单、有效、通用的方法来处理这个问题。请参阅任何其他答案。
这看起来不会阻止用户使用键盘关注链接。屏幕阅读器会发生什么?【参考方案2】:
你可以使用一个作用域函数来返回:
没有状态
现有状态
像这样:
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
href
属性仅在函数返回现有状态字符串时创建。
或者,你可以做一个(丑陋的):
<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>
希望对你有帮助
【讨论】:
在尝试您的checkCondition()
方法时,我仍然遇到控制台错误。它说Could not resolve '-' from state 'home'
我喜欢这个答案,因为它是最快的完成方式。 ui-sref="condition ? '.childState' : '.'"
@chovy a '.'本身而不是 '-' 将返回当前状态
为了防止出错:$rootScope.$on("$stateNotFound", function (event, unfoundState, fromState, fromParams) if (unfoundState.to == '-') event.preventDefault (); 返回; );
@chovy 我遇到了同样的问题,并在返回return $state.href('login', , absolute: true);
后将其放入href="checkCondition()"
【参考方案3】:
在不修改指令、范围等的情况下有条件地实现路由的最简单的解决方法是我在这里找到的解决方法 - https://github.com/angular-ui/ui-router/issues/1489
<a ui-sref="condition ? '.childState' : '.'"> Conditional Link </a>
【讨论】:
【参考方案4】:您总是可以在元素上加倍并有条件地显示/隐藏
<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
【讨论】:
这对我没有帮助,因为我不想让按钮变灰。我只是想弹出一个提示“你要离开了,你确定吗?”【参考方案5】:无需复杂的指令或技巧。以下工作正常,并允许对非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
;
【讨论】:
【参考方案6】:根据How to dynamically set the value of ui-sref
的答案,您可以在自己的范围内创建一个函数来构建 URL:
$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/api/images/get?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>
【讨论】:
【参考方案7】:我知道这是一个老问题,但为了将来参考,我想提供一个替代解决方案,因为到目前为止我没有在任何答案中看到它。
期望:
<li ui-sref-active="active">
<a ui-sref="somestate" ui-sref-if="model.validate()">Go Somestate</a>
</li>
可能的解决方案(模板):
<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');
【讨论】:
【参考方案8】:对于那些仍然需要 ng-click
处理 ui-sref
组件或其父组件的人的可能解决方案。
我的解决方案是使用href
而不是ui-sref
并稍微修改Emanuel's 指令以便能够分别停止href
和ng-click
调用。
Planker.
虽然它有一些限制:
不适用于ui-sref
由于之前的限制,您应该为每个州设置不同的网址
ui-sref-active
也不起作用
【讨论】:
【参考方案9】:对于二进制情况(链接被启用或禁用),它“现在”(自~2018 年以来)的工作方式如下(防止点击并将其设置为禁用):
<a ui-sref="go" ng-disabled="true">nogo</a>
对于其他标签也是如此:
<span ui-sref="go" ng-disabled="true">nogo</span>
【讨论】:
以上是关于如何实现有条件地执行“ui-sref”?的主要内容,如果未能解决你的问题,请参考以下文章