Comment réaliser que" ui-sref " soit exécuté conditionnellement?

je veux valider certaines conditions avant que le navigateur ne suive le lien dynamiquement créé par ui-router.

je cherchais dans $rootscope.$on('$stateChangeStart', ..) mais je n'ai pas accès au controller.$scope de là. Je dois également utiliser ce à plusieurs endroits dans la demande et serait lourd.

Gardez à l'esprit que ui-sref est lié à ui-sref-active (travailler ensemble), donc je ne peux pas supprimer ui-sref et, par exemple, utiliser $state.$go('some-state') à l'intérieur d'une fonction appelée avec ng-click .

la condition doit être évaluée à l'intérieur d'un $scope function et sur on-click event (avant-transition avec la possibilité de l'annuler)

j'ai besoin de quelque chose comme ceci:

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

Pair

<li ui-sref-active="active">
      <a ui-sref="somestate" onclick="return false;">Go Somestate</a>
</li>

Mais ne fonctionne pas.

bac à sable

56
demandé sur Emanuel Ve 2014-09-01 10:36:26

8 réponses

Ce réponse m'a inspiré pour créer une directive qui me permet d'interrompre la chaîne des événements qui finissent par changer d'état. Pour la 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>

PLUNKER

67
répondu Emanuel Ve 2017-05-23 12:34:25

Vous pouvez utiliser une fonction qui renvoie :

  • sans état
  • un état existant

    comme 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 ne sera créé que si la fonction renvoie une chaîne d'état existante.

Alternativement, vous pourriez faire un (laid):

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

Espérons que cette aide

27
répondu Cétia 2014-09-01 08:22:58

Vous pouvez toujours le double sur 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>

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

7
répondu Chris T 2014-09-02 19:07:30

la solution de contournement la plus facile pour obtenir un routage conditionnel sans bricoler avec les directives, le champ d'application, etc était une solution de contournement que j'ai trouvé ici - https://github.com/angular-ui/ui-router/issues/1489

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

7
répondu jetpackdata.com 2017-03-09 16:50:58

basé sur les réponses à comment définir dynamiquement la valeur de ui-sref vous pouvez créer une fonction dans votre portée pour construire L'URL:

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

et ensuite l'ajouter conditionnellement au lien avec ng-href

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

comme vous pouvez le voir dans la démo ci-dessous, ng-href n'ajoute pas l'attribut href si la valeur est négative.

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
répondu fracz 2017-05-23 12:02:39

pas besoin de directives compliquées ou de piratages. Les travaux suivants très bien et permet une manipulation spécifique sur le clic de non - sref articles:

<a 
  ng-repeat="item in items" ui-sref="{{item.sref || '-'}}" 
  ng-click="$ctrl.click(item, $event)"
>...</a>

et dans le contrôleur, un simple click handler pour les éléments qui n'ont pas de item.sref :

this.click = function(item, event) {
  if (!item.sref) {
    event.preventDefault();
    //do something else
  }
};
2
répondu Adam Reis 2016-06-26 01:59:10

je sais que c'est une vieille question, mais pour référence future je voulais offrir une solution alternative car je ne l'ai vu dans aucune des réponses jusqu'à présent.

désiré:

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

solution (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');
  }
}
1
répondu David Meza 2017-05-31 13:19:49

solution Possible pour ceux qui auraient encore besoin de ng-click travailler sur ui-sref composant ou de ses parents.

ma solution est d'utiliser href au lieu de ui-sref et de modifier Emanuel's directive un peu pour pouvoir arrêter href et ng-click séparément.

Planker .

malgré quelques restrictions:

  • ne fonctionnera pas avec ui-sref
  • vous devriez avoir des urls différentes pour chaque État en raison de la restriction précédente
  • ui-sref-active ne fonctionnera pas non plus
0
répondu andrfas 2017-06-29 11:03:48