webentwicklung-frage-antwort-db.com.de

Wie umleiten Sie in einem UI-Router beheben?

Ich versuche innerhalb eines ui-routers eine Weiterleitung durchzuführen und wollte wissen, ob es eine Möglichkeit gibt, einen Router-Resolver umzuleiten. Derzeit funktioniert das nicht so, wie man meinen würde.

resolver(auth, $state){
   if(!auth.isLoggedIn()){
       $state.go('noLoggedInPath');
   }
}

Wie kann man in einem Resolver richtig umleiten?

Mein Temp-Hack ist das, aber ich fühle mich nicht wohl dabei.

resolver(auth, $state, $timeout){
   if(!auth.isLoggedIn()){
        $timeout(function () {

             $state.go('noLoggedInPath');
        }, 0);
   }
}
39
Edgar Martinez

Sie können ein Versprechen von Ihrer resolver-Funktion zurückgeben, die angibt, ob Sie weiter zum Status navigieren möchten oder nicht. Wenn Sie sich entscheiden, zu einem anderen Ort zu navigieren, lehnen Sie das Versprechen ab und geben Sie den richtigen Status an:

resolver($q, $state, $timeout, auth) {
    var deferred = $q.defer();

    // $timeout is an example; it also can be an xhr request or any other async function
    $timeout(function() {
      if (!auth.isLoggedIn()) {
        // user is not logged, do not proceed
        // instead, go to a different page
        $state.go('noLoggedInPath');
        deferred.reject();
      } else {
        // everything is fine, proceed
        deferred.resolve();
      }
    });

    return deferred.promise;
}

Plunkr hier .

UPD: aktualisierter Code und hinzugefügter Plunkr. Sieht so aus, als würde es nur funktionieren, wenn Sie eine Timeout-Funktion verwenden.

37

Yauhenis Antwort funktioniert, aber um die seltsame Zeitüberschreitung zu umgehen, können Sie das Versprechen ablehnen und dies im $ stateChangeError-Ereignis einfangen und dort Ihre Weiterleitung durchführen. Wie so ...

state('admin', {
  resolve: {
    auth: function(UserService, $q, permissionService) {
      var deferred = $q.defer();
      return UserService.load().then(function(user){
        if (permissionService.can(user, {goTo: state})) {
          return deferred.resolve({});
        } else {
          return deferred.reject({redirectTo: 'some_other_state'});
        }
      });
    }
  }
});

Und dann sendet der ui-router immer "stateChangeError", so dass Sie so etwas tun können.

$rootScope.$on('$stateChangeError', function(evt, to, toParams, from, fromParams, error) {
  if (error.redirectTo) {
    $state.go(error.redirectTo);
  } else {
    $state.go('error', {status: error.status})
  }
})
46
bwest87

Ich benutze das

   function Check($state, $q) {
        var deferred = $q.defer();
        if (condition) {
            deferred.resolve();
        }
        else {
            deferred.reject();
        }
        return deferred.promise.catch(function () { $state.go('path'); });
    }
6
Hikmat G.

Das mache ich tatsächlich und ich kann keine bessere Lösung finden

resolver($q, $timeout, myService) {
    if(!areParameterValuesValid() || !isEverythingLogicallyOk()){
        var deferred = $q.defer();
        $timeout(function() {
            $state.go('somewhere');
            deferred.reject();
        });
        return deferred.promise;
    } else {
        return myService.loadSomething(passingSomeParams);
    }        
}
2
Hovo

Ich denke, eine viel sauberere Antwort ist, ein bereits abgelehntes Versprechen wie folgt zurückzugeben:

resolver(auth, $state, $q){
   if(!auth.isLoggedIn()){
       $state.go('noLoggedInPath');
       
       // Return rejected promise
       return $q.reject();
   }
   return true;
}

1
Tibo

Die Verwendung von Vorsätzen für dieses Problem hat sich für mich nicht ganz bewährt. Ich habe die Logik von this post angepasst, um eine Umleitungsfunktion für die data - Eigenschaft des Zustandsobjekts auszuführen. Sie können dann das $ stateChangeStart -Ereignis auf $ rootScope aus dem Ausführungsblock des Moduls aufrufen und die Invoke-Methode des Injector-Service verwenden, um den Status basierend auf den von Ihnen angegebenen Bedingungen zu ändern. Funktioniert auch gut zwischen Modulen.

0
Andrew Leonardi

Sie können Resolver-Versprechen mit der redirectTo-Konfiguration verwenden

   redirectTo: function($transition$) {
      return $transition$.injector().getAsync('isNew').then(function(isNew) {
        return isNew ? 'estate.edit' : 'estate.view';
      });
    },
0
Blowsie