webentwicklung-frage-antwort-db.com.de

Wie kann man erreichen, dass "ui-sref" bedingt ausgeführt wird?

Ich möchte bestimmte Bedingungen überprüfen, bevor der Browser dem vom UI-Router dynamisch erstellten Link folgt. 

Ich habe mir $rootscope.$on('$stateChangeStart', ..) angesehen, aber von dort aus habe ich keinen Zugriff auf den controller.$scope. Ich muss dies auch an mehreren Stellen in der Anwendung verwenden und wäre umständlich. 

Denken Sie daran, dass ui-sref mit ui-sref-active (zusammenarbeiten) verknüpft ist. Daher kann ich ui-sref nicht entfernen und beispielsweise $state.$go('some-state') in einer Funktion verwenden, die mit ng-click aufgerufen wird.

Die Bedingung sollte in einem $scope function und auf on-click event (vor dem Übergang mit der Möglichkeit zum Abbrechen) ausgewertet werden.

Ich brauche so etwas:

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

Ich habe es versucht:

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

Und

<li ui-sref-active="active">
    <a ui-sref="somestate">
       <span ng-click="$event.stopPropagation();">Go Somestate</span>
    </a>
</li>

Sogar

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

Funktioniert aber nicht.

SANDKASTEN

56
rnrneverdies

Diese Antwort hat mich dazu inspiriert, eine Direktive zu erstellen, die es mir ermöglicht, die Kette von Ereignissen zu unterbrechen, die den Status ändern. Aus Bequemlichkeits- und anderen Gründen wird auch die Ausführung von ng-click auf dasselbe Element verhindert.

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

Sie können eine Bereichsfunktion verwenden, die Folgendes zurückgibt:

  • kein Zustand
  • ein bestehender Staat

    wie so:

HTML:

<li ui-sref-active="active">
      <a ui-sref="{{checkCondition()}}">Go Somestate</a>
</li>

JS Umfang:

$scope.checkCondition = function() {
    return model.validate()
        ? 'someState'
        : '-' // hack: must return a non-empty string to prevent JS console error
}

Das href-Attribut wird nur erstellt, wenn die Funktion eine vorhandene Statuszeichenfolge zurückgibt.

Alternativ können Sie (hässlich) Folgendes tun:

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

Hoffe das hilft

27
Cétia

Die einfachste Problemumgehung, um bedingtes Routing zu erreichen, ohne Richtlinien, Gültigkeitsbereiche usw. zu ändern, war eine Problemumgehung, die ich hier gefunden habe - https://github.com/angular-ui/ui-router/issues/1489

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

9
jetpackdata.com

Sie können das Element jederzeit verdoppeln und bedingt anzeigen/ausblenden

    <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

Keine Notwendigkeit für komplizierte Anweisungen oder Hacks. Das Folgende funktioniert gut und ermöglicht eine spezifische Handhabung beim Klicken auf nicht -sref Elemente:

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

Und in der Steuerung ein einfacher Klick-Handler für die Elemente, die keinen item.sref haben:

this.click = function(item, event) {
  if (!item.sref) {
    event.preventDefault();
    //do something else
  }
};
3
Adam Reis

Basierend auf den Antworten auf So legen Sie den Wert von ui-sref Dynamisch fest können Sie in Ihrem Gültigkeitsbereich eine Funktion zum Erstellen der URL erstellen:

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

Und hängen Sie es dann an den Link mit ng-href an

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

Wie Sie in der Demo unten sehen können, fügt ng-href Das href -Attribut nicht hinzu, wenn der Wert negativ ist.

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

Ich weiß, dass dies eine alte Frage ist, aber ich wollte für eine zukünftige Referenz eine alternative Lösung anbieten, da ich sie in keiner der Antworten bisher gesehen habe.

Gewünschte:

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

Mögliche Lösung (Vorlage):

<li ng-class="{ active: state.current.name === 'somestate' }">
    <a ng-click="navigateToState()">Go Somestate</a>
</li>

Und im Controller:

$scope.state = $state;
$scope.navigateToState = navigateToState;

function navigateToState() {
  if ($scope.model.valid) {
    $state.go('somestate');
  }
}
1
David Meza

Mögliche Lösung für diejenigen, die ng-click noch an ui-sref-Komponente oder deren übergeordneten Komponenten arbeiten müssen.

Meine Lösung ist, href anstelle von ui-sref zu verwenden und Emanuels - Direktive ein bisschen zu ändern, um href- und ng-click-Aufrufe separat beenden zu können. 

Planker .

Es gibt jedoch einige Einschränkungen:

  • funktioniert nicht mit ui-sref
  • sie sollten unterschiedliche URLs für jeden Status haben, da zuvor Einschränkungen aufgetreten sind
  • ui-sref-active wird auch nicht funktionieren
0
andrfas