Je veux valider certaines conditions avant que le navigateur ne suive le lien créé dynamiquement par ui-router.
Je cherchais dans $rootscope.$on('$stateChangeStart', ..)
mais je n'ai pas accès au controller.$scope
à partir de là. J'ai également besoin de l'utiliser à plusieurs endroits de l'application, ce qui serait fastidieux.
N'oubliez pas que ui-sref
est lié à ui-sref-active
(fonctionne ensemble), je ne peux donc pas supprimer ui-sref
et, par exemple, utiliser $state.$go('some-state')
dans une fonction appelée avec ng-click
.
La condition doit être évaluée dans un $scope function
et sur on-click event
(avant-transition avec la possibilité de l'annuler)
J'ai besoin de quelque chose comme ça:
<li ui-sref-active="active">
<a ui-sref="somestate" ui-sref-if="model.validate()">Go Somestate</a>
</li>
J'ai essayé:
<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>
Et
<li ui-sref-active="active">
<a ui-sref="somestate">
<span ng-click="$event.stopPropagation();">Go Somestate</span>
</a>
</li>
Même
<li ui-sref-active="active">
<a ui-sref="somestate" onclick="return false;">Go Somestate</a>
</li>
Mais ça ne marche pas.
Cette réponse m'a inspiré pour créer une directive qui me permet d'interrompre la chaîne d'événements qui finissent par changer d'état. Pour des raisons de commodité et d’autres utilisations, empêche également l’exécution de ng-click sur le même élément.
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>
Vous pouvez utiliser une fonction de portée qui renverra soit:
un état existant
ainsi :
HTML:
<li ui-sref-active="active">
<a ui-sref="{{checkCondition()}}">Go Somestate</a>
</li>
JS portée:
$scope.checkCondition = function() {
return model.validate()
? 'someState'
: '-' // hack: must return a non-empty string to prevent JS console error
}
L'attribut href
sera créé uniquement lorsque la fonction renvoie une chaîne d'état existante.
Alternativement, vous pouvez faire un (moche):
<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>
J'espère que cela t'aides
La solution de contournement la plus simple pour réaliser conditionnellement un routage sans modifier les directives, la portée, etc. était une solution de contournement trouvée ici - https://github.com/angular-ui/ui-router/issues/1489
<a ui-sref="{{condition ? '.childState' : '.'}}"> Conditional Link </a>
Vous pouvez toujours doubler l'élément et afficher/masquer conditionnellement
<li ui-sref-active="active">
<a ng-show="condition1" style="color: grey">Start</a>
<a ng-hide="condition1" ui-sref="start">Start</a>
</li>
Pas besoin de directives compliquées ou hacks. Ce qui suit fonctionne bien et permet un traitement spécifique au clic d’éléments non -sref
:
<a
ng-repeat="item in items" ui-sref="{{item.sref || '-'}}"
ng-click="$ctrl.click(item, $event)"
>...</a>
Et dans le contrôleur, un simple gestionnaire de clic pour les éléments qui n’ont pas de item.sref
:
this.click = function(item, event) {
if (!item.sref) {
event.preventDefault();
//do something else
}
};
Je sais que c’est une vieille question, mais pour référence future, je souhaitais proposer une solution de remplacement car je ne l’avais pas trouvée dans les réponses jusqu’à présent.
Souhaité:
<li ui-sref-active="active">
<a ui-sref="somestate" ui-sref-if="model.validate()">Go Somestate</a>
</li>
Solution potentielle (modèle):
<li ng-class="{ active: state.current.name === 'somestate' }">
<a ng-click="navigateToState()">Go Somestate</a>
</li>
Et dans le contrôleur:
$scope.state = $state;
$scope.navigateToState = navigateToState;
function navigateToState() {
if ($scope.model.valid) {
$state.go('somestate');
}
}
Solution possible pour ceux qui ont encore besoin de ng-click
travailler sur le composant ui-sref
ou ses parents.
Ma solution est d'utiliser href
au lieu de ui-sref
et de modifier légèrement la directive Emanuel pour pouvoir arrêter les appels href
et ng-click
séparément.
Planker .
Bien qu'il y ait quelques restrictions:
ui-sref
ui-sref-active
ne fonctionnera pas non plus