web-dev-qa-db-fra.com

Comment conserver le paramètre d'état optionnel sur le navigateur dans ui-router?

J'ai un état parent qui a l'état de deux enfants à l'intérieur duquel je vais montrer un état basé sur URL.

Parmi ces deux states on doit avoir des paramètres comme param1 et param2, j'ai utiliser l'option params de ui-router dans la définition d'état.

Etat

$stateProvider.state('tabs.account', {
    url: '/account',
    views: {
        'content@tabs': {
            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
    }
});

Si vous regardez ma route, l'option params n'est pas vraiment introduite dans URL, c'est pourquoi je considère que cela est facultatif. 

Problème

Regardez plunkr, j'ai montré deux onglets Compte & Enquête

  1. Cliquez sur l'onglet Enquête, puis ajoutez des données dans la variable textarea qui sont affichées. 
  2. Cliquez sur Go to Account pour transmettre ces valeurs textarea à L'autre onglet Account en faisant ui-sref="tabs.account({param1: thing1, param2: thing2})" sur l'ancre.

  3. Maintenant, vous verrez les valeurs param1 & param2 sur le HTML qui a été attribué à scope de $stateParams

  4. Maintenant, cliquez à nouveau sur l'onglet Survey pour accéder à la page d'enquête.
  5. Cliquez simplement sur le navigateur en arrière, vous remarquerez que la valeur param ne reçoit pas null.

Problem Plunkr

Je crois que vous avez ce que je voulais demander, pourquoi la valeur du paramètre facultatif n’a pas été stockée? comme ils ont fait partie de l'état.

Je sais que je peux résoudre ce problème en présentant ci-dessous deux solutions.

  • En créant un service qui partagera les données entre deux vues.
  • En ajoutant un paramètre à l'intérieur de l'URL d'état. comme url: '/account/:param1/:param2', (mais je ne préférerais pas cela)

J'ai déjà essayé angular-ui-routers sticky states mais cela ne semble pas fonctionner pour moi. Quel est le meilleur moyen d'y parvenir?

Existe-t-il un moyen de faire fonctionner mon cas d'utilisation? Toutes les idées seraient appréciées.

Github Issue Link Here

28
Pankaj Parkar

Une solution workaround consiste à mettre en cache les paramètres d'état et à les charger de manière conditionnelle lors de la saisie de l'état tabs.account. La configuration de l'état du routeur d'interface utilisateur vous permet en fait de fournir un rappel onEnter pour ces types de situations "faire quelque chose en entrant dans l'état".

Voici la logique de base utilisant localStorage comme cache, avec Plunker ici :

  • Lorsque vous entrez l'état tabs.account, vérifiez vos paramètres d'état
    • Si vous en avez, mettez-les en cache dans le stockage local
    • Sinon, chargez-les à partir de la mémoire de stockage locale dans $stateParams

Voici un exemple d'extrait de code pour référence (tiré du 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');
      }
    }],
    ...
  }

Un caveat est que vos paramètres persisteront indéfiniment (par exemple, lors de mises à jour et de sessions). Pour résoudre ce problème, vous pouvez vider le cache au chargement de l’application comme dans app.run.

Une dernière remarque est que dans Plunker, j'accède directement au stockage local (via le service Angular $window). Vous voudrez peut-être utiliser un module AngularJS - j'ai déjà utilisé angular-local-storage in production.

7
Christian Yang

Je crois que ce que vous voulez réaliser n'est pas possible sans utiliser l'une des deux solutions que vous avez fournies.

Le bouton Précédent du navigateur ne fait que conserver l'historique des URL. Il n'a aucune idée des états internes du routeur ui et va simplement forcer l'URL à changer.

Forcer l'URL à changer déclenchera la machine interne du routeur ui, mais malheureusement, ui-router verra l'URL changer de la même façon que si quelqu'un aurait changé l'URL manuellement.

Ui-router lancera un nouveau changement d'itinéraire sur l'itinéraire indiqué par l'URL. Cela signifie qu'il ne sait pas que vous vouliez revenir en arrière et changera simplement d’état pour le nouveau sans aucun paramètre.

Résumé

En cliquant sur le bouton de retour, un changement d'état devient un new state en fonction de l'URL au lieu de revenir à l'état précédent.

C'est pourquoi l'ajout des paramètres à l'URL résout le problème. Puisque l'URL est discriminatoire, vous allez finalement atterrir sur l'état souhaité.

J'espère que ça a aidé. 

2
Okazari

Pour moi, cela ressemble à problème X Y . Il existe des méthodes suggérées pour rendre les paramètres d'état persistants, alors que le problème se situe hors de cette surface. 

Selon la définition de la question, il existe des données qui doivent être conservées indépendamment des États. Donc, c'est un peu global par rapport aux États. Ainsi, il devrait exister un service qui le conserve et les contrôleurs des deux États le maintiennent au besoin. Il suffit de ne pas transmettre de données qui sortent du cadre d’un État dans les paramètres d’état.

Les états collants conviendraient facilement à cette approche, car elle permet de conserver DOM et $scope tant qu'un autre état est actif. Mais cela n'a rien à voir avec les paramètres d'état lorsque l'état est réactivé. 

0
Kirill Slatin