ブラウザーがui-routerによって動的に作成されたリンクをたどる前に、特定の条件を検証します。
$rootscope.$on('$stateChangeStart', ..)
を探していましたが、そこからcontroller.$scope
にアクセスできません。また、アプリケーション内のいくつかの場所でこれを使用する必要があり、面倒です。
ui-sref
はui-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>
しかし、動作しません。
これ 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>
次のいずれかを返すスコープ関数を使用できます。
既存の状態
そのようです :
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>
お役に立てれば
ディレクティブ、スコープなどをいじらずに条件付きでルーティングを達成するための最も簡単な回避策は、私がここで見つけた回避策でした- 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>
複雑な指令やハッキングの必要はありません。以下は正常に機能し、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
}
};
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>
これは古い質問であることはわかっていますが、今後の参考のために、これまでのところどの回答にも見られなかったため、代替ソリューションを提供したいと考えました。
望ましい:
<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');
}
}