it-swarm.com.de

Wie kann man optionale Zustandsparameter im Browser wieder im UI-Router beibehalten?

Ich habe einen übergeordneten Zustand, in dem sich zwei Kinder befinden, in dem ich einen Zustand basierend auf URL anzeigen werde.

Von diesen beiden states muss man Parameter wie param1 und param2 verwenden. Ich habe die Option params von ui-router in der Zustandsdefinition.

Zustand

$stateProvider.state('tabs.account', {
    url: '/account',
    views: {
        '[email protected]': {
            templateUrl: 'account.html',
            controller: function($scope, $stateParams) {
                //This params are internally used to make ajax and show some data.
                $scope.param1 = $stateParams.param1;
                $scope.param2 = $stateParams.param2;
            },
        }
    },
    params: {
        param1: { value: null }, //this are optional param
        param2: { value: null } //because they are not used in url
    }
});

Wenn Sie sich meine Route ansehen, wird die Option params nicht wirklich in URL eingeführt. Deshalb erwäge ich sie als optional. 

Problem

Schau dir plunkr an, ich habe zwei Tabs angezeigt Account & Survey

  1. Klicken Sie auf die Registerkarte Umfrage, und fügen Sie dann in der Liste textarea einige Daten hinzu. 
  2. Klicken Sie auf Gehe zu Konto, um diese Werte an textarea an den anderen Account -Regler zu übergeben, indem Sie ui-sref="tabs.account({param1: thing1, param2: thing2})" auf dem Anker ausführen

  3. Nun sehen Sie die param1 & param2-Werte in HTML, die dem Bereich von $stateParams zugewiesen wurden.

  4. Klicken Sie nun erneut auf die Registerkarte Umfrage. Sie gelangen auf die Umfrageseite.
  5. Klicken Sie einfach auf den Browser zurück, und Sie werden feststellen, dass der Wert param nicht null erhält.

Problem Plunkr

Ich glaube, Sie haben das bekommen, was ich fragen wollte, warum der optionale Parameterwert nicht gespeichert wurde. wie sie ein Teil des Staates waren.

Ich weiß, dass ich dieses Problem durch zwei Lösungen lösen kann.

  • Erstellen Sie einen Dienst, der Daten zwischen zwei Ansichten teilt.
  • Durch Hinzufügen von Parametern in der Status-URL. wie url: '/account/:param1/:param2', (aber ich würde das nicht vorziehen)

Ich habe schon eckige-ui-routers sticky states ausprobiert, aber das scheint für mich nicht zu funktionieren. Was ist der bessere Weg dazu?

Gibt es eine Möglichkeit, wie ich meinen Use Case zum Laufen bringen kann? Alle Ideen würden uns freuen.

Github Issue Link hier

28
Pankaj Parkar

Ich würde die params -Definition in den übergeordneten Zustand verschieben, um die optionalen Zustandsparameter zwischen Ihren beiden untergeordneten Zuständen zu teilen.

Die untergeordneten Staaten erben die $stateParams von deinen Eltern, als solche ist keine wirkliche "Problemumgehung" erforderlich.

Einfach spritzen $stateParams wie in Ihren untergeordneten Controllern üblich, und Sie haben vollen Zugriff auf die Parameter, die weitergegeben werden. Wenn Sie die Parameter nicht in einem bestimmten untergeordneten Zustand verwenden möchten, vermeiden Sie es einfach, sie zu injizieren.

Das funktioniert mit;

  • Zurück-Button
  • Vorwärts-Taste
  • ui-sref (ohne Parameter (bleibt unverändert))
  • ui-sref (mit Parametern (wird überschrieben))

$stateProvider
  .state('parent', {
    params: { p1: null, p2: null }
  })
  .state('parent.childOne', {
    url: '/one',
    controller: function ($stateParams) {
      console.log($stateParams); // { p1: null, p2: null }
    }
  })
  .state('parent.childTwo', {
    url: '/two',
    controller: function ($stateParams) {
      console.log($stateParams); // { p1: null, p2: null }
    }
  })

Wenn Sie zu irgendeinem Zeitpunkt löschen die Parameter während der Fahrt innerhalb des Zustandsbaums von parent löschen möchten, müssten Sie dies manuell tun.

Das wäre die only wirkliche Einschränkung, die ich bei Verwendung dieser Lösung sehen kann.

Ich stelle fest, dass manuelles Löschen in dem Fall, in dem Sie anwesend sind, möglicherweise nicht wünschenswert ist, aber Sie haben sich nicht aktiv dagegen ausgesprochen, weshalb ich der Meinung bin, dass der Vorschlag sinnvoll ist.

aktualisierter Plunker

20
Kasper Lewau

Eine workaround - Lösung besteht darin, die Zustandsparameter zwischenzuspeichern und sie beim Eintritt in den tabs.account-Zustand bedingt zu laden. Mit der UI-Router-Statuskonfiguration können Sie tatsächlich einen onEnter-Rückruf für diese Arten von Situationen bereitstellen, bei denen "beim Eintreten des Status etwas unternommen wird".

Hier ist die grundlegende Logik, die localStorage als Cache verwendet, wobei der Plunker hier funktioniert:

  • Wenn Sie den tabs.account-Status eingeben, prüfen Sie, ob die Statusparameter ________ vorhanden sind.
    • Wenn Sie sie haben, zwischenspeichern Sie sie im lokalen Speicher
    • Wenn nicht, laden Sie sie aus dem lokalen Speicher in $stateParams.

Hier ein Beispiel-Code-Snippet als Referenz (aus dem Plunker):

  $stateProvider.state('tabs.account', {
    ...
    onEnter: ['$stateParams', '$window', function($stateParams, $window) {
      if($stateParams.param1) {
        $window.localStorage.setItem('tabs.account.param1', $stateParams.param1);
      } else {
        $stateParams.param1 = $window.localStorage.getItem('tabs.account.param1');
      }
      if($stateParams.param2) {
        $window.localStorage.setItem('tabs.account.param2', $stateParams.param2);
      } else {
        $stateParams.param2 = $window.localStorage.getItem('tabs.account.param2');
      }
    }],
    ...
  }

Ein Vorbehalt ist, dass Ihre Parameter auf unbestimmte Zeit bestehen bleiben (z. B. zwischen Aktualisierungen und Sitzungen). Um dies zu umgehen, können Sie den Cache beim Laden der Anwendung wie in app.run löschen.

Eine letzte Anmerkung ist, dass ich im Plunker direkt auf den lokalen Speicher zugreife (über den Angular $window-Dienst). Möglicherweise möchten Sie ein AngularJS-Modul verwenden - ich habe angle-local-storage in der Produktion verwendet.

7
Christian Yang

Ich glaube, dass das, was Sie erreichen möchten, nicht möglich ist, ohne eine der beiden Lösungen zu verwenden, die Sie bereitgestellt haben.

Die Zurück-Schaltfläche des Browsers speichert nur den URL-Verlauf. Er hat keine Ahnung von den internen Zuständen des UI-Routers und erzwingt nur die Änderung der URL.

Das Erzwingen der URL zum Ändern löst einen internen UI-Router aus, aber leider wird der UI-Router die Änderung der URL genauso sehen, als ob jemand die URL manuell geändert hätte.

Der Ui-Router löst eine neue Routenänderung an der Route aus, auf die die URL verweist. Das heißt, er weiß nicht, dass Sie "zurück" gehen wollten, und wechselt den Zustand ohne Parameter in den neuen Zustand.

Zusammenfassung

Durch Klicken auf die Schaltfläche "Zurück" wird ein Zustandswechsel in einen new - Zustand gemäß der URL ausgelöst, anstatt zum vorherigen Zustand zurückzukehren.

Daher lösen Sie das Problem, wenn Sie der URL die Parameter hinzufügen. Da die URL diskriminierend ist, landen Sie endlich in dem von Ihnen gewünschten Staat.

Hoffe es hat geholfen. 

2
Okazari

Für mich klingt dies als X Y Problem . Es gibt Möglichkeiten, Statusparameter dauerhaft zu machen, während das Problem außerhalb dieser Oberfläche liegt. 

Per Definition der Frage gibt es Daten, die von Staaten unabhängig bleiben sollten. Es ist also eine Art globales Verhältnis zu Staaten. Daher sollte es einen Dienst geben, der es hält, und die Controller beider Staaten behalten es bei Bedarf bei. Übergeben Sie einfach keine Daten, die außerhalb der Zustände eines Staates in Zustandsparametern liegen.

Sticky-Zustände würden leicht zu diesem Ansatz passen, da DOM und $scope beibehalten werden können, während ein anderer Status aktiv ist. Es hat jedoch nichts mit Zustandsparametern zu tun, wenn der Staat reaktiviert wird. 

0
Kirill Slatin