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

IT技术 javascript angularjs angular-ui-router
2021-03-14 15:59:43

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

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

请记住,ui-sref它与ui-sref-active(一起工作)相关联,所以我无法删除ui-sref,也就是说,$state.$go('some-state')在调用 with 的函数中使用ng-click

条件应该在 a$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>

但不起作用。

沙盒

6个回答

这个答案激励我创建一个指令,允许我中断最终改变状态的事件链。为了方便和其他用途,还可以防止在同一元素上执行 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>

普伦克

他们真的应该包括这个功能。它可以重命名为ui-sref-disable. 考虑打开一个拉取请求,@OneWay!
2021-04-21 15:59:43
这看起来不会阻止用户使用键盘关注链接。屏幕阅读器会发生什么?
2021-04-23 15:59:43
这太棒了。谢谢你的这个小插曲。我同意@DesignerGuy,应该是ui-sref-disabled
2021-04-28 15:59:43
@DesignerGuy ...我们做到了,这就是他们回答我们要做的:复制这个module:-D :-D :-D ---- 这里是链接----> github.com/angular-ui /ui-router/issues/…
2021-05-10 15:59:43
这是一种解决方法。有更简单、有效、通用的方法来处理这个问题。参考任何其他答案。
2021-05-20 15:59:43

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

  • 没有状态

  • 现有状态

    像这样:

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>

希望这可以帮助

@chovy '.' 本身而不是 '-' 将返回当前状态
2021-04-22 15:59:43
尝试您的checkCondition()方法时,我仍然收到控制台错误它说Could not resolve '-' from state 'home'
2021-04-30 15:59:43
防止错误: $rootScope.$on("$stateNotFound", function (event, unfoundState, fromState, fromParams) { if (unfoundState.to == '-') { event.preventDefault(); return; }}) ;
2021-05-08 15:59:43
我喜欢这个答案,因为它是最快的方法。 ui-sref="{{condition ? '.childState' : '.'}}"
2021-05-19 15:59:43
@chovy 我遇到了同样的问题,并href="checkCondition()"在返回后将其放入return $state.href('login', {}, {absolute: true});
2021-05-21 15:59:43

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

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

您始终可以在元素上加倍并有条件地显示/隐藏

    <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

这对我没有帮助,因为我不想使按钮变灰。我只是想弹出一个警告,上面写着“你要离开了,你确定吗?”
2021-04-26 15:59:43

不需要复杂的指令或黑客。以下工作正常,并允许在点击非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
  }
};