如何实现"ui-sref"有条件执行?

rnr*_*ies 59 javascript angularjs angular-ui-router

我想在浏览器遵循ui-router动态创建的链接之前验证某些条件.

我正在调查,$rootscope.$on('$stateChangeStart', ..)但我无法访问controller.$scope那里.我还需要在应用程序的几个地方使用它,并且会很麻烦.

请记住ui-sref链接到ui-sref-active(一起工作),所以我不能删除,ui-sref并且说,$state.$go('some-state')在一个名为with的函数内使用ng-click.

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

我需要这样的东西:

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

我试过了:

<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>
Run Code Online (Sandbox Code Playgroud)

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

甚至

<li ui-sref-active="active">
      <a ui-sref="somestate" onclick="return false;">Go Somestate</a>
</li>
Run Code Online (Sandbox Code Playgroud)

但是不起作用.

SANDBOX

rnr*_*ies 67

这个答案激发了我创建一个指令,允许我中断最终改变状态的事件链.为方便起见,其他用途也会阻止在同一元素上执行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() {}
        }
      }
    }
  }
]);
Run Code Online (Sandbox Code Playgroud)

HTML

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

PLUNKER

  • 这太棒了.谢谢你的这个tid位.我同意@DesignerGuy,它应该是'ui-sref-disabled` (5认同)
  • 他们应该真的包含这个功能.它可以重命名为`ui-sref-disable`.考虑打开拉取请求,@ OneWay! (4认同)

Cét*_*tia 27

您可以使用将返回的范围函数:

  • 没有国家
  • 现有的国家

    像这样:

HTML:

<li ui-sref-active="active">
      <a ui-sref="{{checkCondition()}}">Go Somestate</a>
</li>
Run Code Online (Sandbox Code Playgroud)

JS范围:

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

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>
Run Code Online (Sandbox Code Playgroud)

希望这可以帮助

  • 我喜欢这个答案,因为这是最快的方法.`ui-sref ="{{condition?'.childState':'.'}}"` (5认同)
  • 尝试`checkCondition()`方法时,我仍然遇到控制台错误.它说'无法解决' - '来自州'家' (3认同)
  • @chovy a'.' 单独而不是' - '将返回当前状态 (3认同)

jet*_*com 9

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

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


Chr*_*s T 7

您可以随时加倍元素并有条件地显示/隐藏

    <li ui-sref-active="active">
          <a ng-show="condition1" style="color: grey">Start</a>
          <a ng-hide="condition1" ui-sref="start">Start</a>
    </li>
Run Code Online (Sandbox Code Playgroud)

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