web-dev-qa-db-ja.com

「ui-sref」を条件付きで実行するにはどうすればよいですか?

ブラウザーがui-routerによって動的に作成されたリンクをたどる前に、特定の条件を検証します。

$rootscope.$on('$stateChangeStart', ..)を探していましたが、そこからcontroller.$scopeにアクセスできません。また、アプリケーション内のいくつかの場所でこれを使用する必要があり、面倒です。

ui-srefui-sref-activeにリンクされている(一緒に動作する)ので、ui-srefを削除できず、たとえば、で呼び出される関数内で$state.$go('some-state')を使用できないng-click

条件は$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>

しかし、動作しません。

サンドボックス

59
rnrneverdies

これ 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

67
rnrneverdies

次のいずれかを返すスコープ関数を使用できます。

  • 状態なし
  • 既存の状態

    そのようです :

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属性は、関数が既存の状態文字列を返す場合にのみ作成されます。

または、(ugい)を行うことができます:

<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>

お役に立てれば

27
Cétia

ディレクティブ、スコープなどをいじらずに条件付きでルーティングを達成するための最も簡単な回避策は、私がここで見つけた回避策でした- https://github.com/angular-ui/ui-router/issues/1489

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

9
jetpackdata.com

いつでも要素をダブルアップして、条件付きで表示/非表示できます

    <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

7
Chris T

複雑な指令やハッキングの必要はありません。以下は正常に機能し、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
  }
};
3
Adam Reis

ui-srefの値を動的に設定する方法 への回答に基づいて、URLを構築するスコープ内に関数を作成できます。

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

そして、条件付きで ng-href でリンクに追加します

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

以下のデモでわかるように、値が負の場合、ng-hrefhref属性を追加しません。

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>
2
fracz

これは古い質問であることはわかっていますが、今後の参考のために、これまでのところどの回答にも見られなかったため、代替ソリューションを提供したいと考えました。

望ましい:

<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');
  }
}
1
David Meza

ng-clickコンポーネントまたはその親で作業するui-srefをまだ必要とする人のための可能な解決策。

私の解決策は、ui-srefの代わりにhrefを使用し、 Emanuel's ディレクティブを少し変更して、hrefng-click呼び出しを個別に停止できるようにすることです。

プランカー

ただし、いくつかの制限があります。

  • ui-srefでは機能しません
  • 以前の制限のため、状態ごとに異なるURLを使用する必要があります
  • ui-sref-activeも機能しません
0
andrfas