template stateprovider sref example javascript angularjs angular-ui-router angular-ui angularjs-routing

javascript - stateprovider - ui view angular js



¿Cómo persistir el parámetro de estado opcional en el navegador de vuelta en ui-router? (4)

Tengo un estado principal que tiene un estado de dos hijos en el que voy a mostrar un estado basado en la URL .

De esos dos states uno tiene que tener parámetros como param1 y param2 , tengo la opción de usar params de ui-router dentro de la definición de estado.

Estado

$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 miras mi ruta, la opción params no se introduce realmente dentro de la URL , por eso lo considero como opcional.

Problema

Mira plunkr, he mostrado dos pestañas Cuenta y Encuesta ,

  1. Haga clic en la pestaña Encuesta, luego agregue algunos datos en el área de textarea que se muestran.
  2. Haga clic en Ir a la cuenta que pasará esos valores de área de textarea a la otra pestaña de la cuenta haciendo ui-sref="tabs.account({param1: thing1, param2: thing2})" en el ancla

  3. Ahora verá los valores de param1 y param2 en html que se ha asignado al alcance desde $stateParams

  4. Ahora de nuevo, haga clic en la pestaña Encuesta , aterrizará en la página de encuesta.
  5. Simplemente haga clic en el navegador de nuevo, se dará cuenta de que el valor param no se está volviendo null .

Problema Plunkr

Creo que tienes lo que quería preguntar, ¿por qué el valor del parámetro opcional no se ha almacenado? Como han sido parte del estado.

Sé que puedo resolver este problema por debajo de dos soluciones.

  • Al crear un servicio que compartirá datos entre dos vistas.
  • Añadiendo parámetro dentro de la URL del estado. como url: ''/account/:param1/:param2'', (Pero no preferiría esto)

Ya probé sticky states enrutadores ui angulares, pero eso no parece funcionar para mí. ¿Cuál es la mejor manera de esto?

¿Hay alguna manera por la cual pueda hacer que mi caso de uso funcione? Cualquier idea lo apreciaría.

Enlace de problema de Github aquí


Creo que lo que quiere lograr no es posible sin usar una de las dos soluciones que proporcionó.

El botón de retroceso del navegador solo mantiene el historial de URL. No tiene ni idea de los estados internos de ui-router y solo forzará el cambio de la URL.

Forzar el cambio de la URL activará la máquina interna del ui-router, pero desafortunadamente el ui-router verá el cambio de la URL como si alguien hubiera cambiado la url a mano.

Ui-router disparará un nuevo cambio de ruta a la ruta señalada por la URL. Eso significa que él no sabe que usted quería volver "atrás" y simplemente cambiará el estado al nuevo sin ningún parámetro.

Resumen

Al hacer clic en el botón Atrás se activará un cambio de estado a un nuevo estado de acuerdo con la URL en lugar de volver al estado anterior.

Es por esto que agregar los parámetros a la URL resuelve el problema. Como la URL es discriminatoria, finalmente aterrizará en el estado que quería.

Espero que haya ayudado.


Para mí esto suena como un problema XY . Se sugieren formas de hacer que los parámetros de estado sean persistentes, mientras que el problema se encuentra fuera de esta superficie.

Por definición de la pregunta, hay datos que deben mantenerse independientes de los estados. Así que es un tipo de relación global con los estados. Por lo tanto, debe haber un servicio que lo mantenga y los controladores de ambos estados lo mantengan según sea necesario. Simplemente no pase datos que estén fuera del alcance de un estado en parámetros de estado.

Los estados adhesivos se adaptarían fácilmente a este enfoque, ya que permite mantener DOM y $scope mientras otro estado está activo. Pero no tiene nada que ver con los parámetros de estado cuando el estado se reactiva.


Una solución alternativa es almacenar en caché los parámetros de estado y cargarlos condicionalmente al ingresar el estado tabs.account . La configuración de estado de UI Router en realidad le permite proporcionar una devolución de llamada onEnter para estos tipos de situaciones de "hacer algo al ingresar al estado".

Aquí está la lógica básica usando localStorage como el caché, con Plunker trabajando here :

  • Cuando ingrese el estado tabs.account , verifique los tabs.account de su estado
    • Si los tiene, guárdelos en el almacenamiento local.
    • Si no lo hace, cárguelos desde el almacenamiento local en $stateParams

Aquí hay un fragmento de código de ejemplo para referencia (tomado de 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''); } }], ... }

Una advertencia es que sus parámetros persistirán indefinidamente (por ejemplo, a través de actualizaciones y sesiones). Para app.run esto, puede borrar el caché en la carga de la aplicación como en app.run .

Una última nota es que en Plunker, estoy accediendo directamente al almacenamiento local (a través del servicio de $window Angular $window ). Es posible que desee utilizar algún módulo AngularJS: he utilizado angular-local-storage en la producción.


params definición de params al estado principal, para compartir los parámetros de estado opcionales entre sus dos estados secundarios.

Los estados secundarios heredarán los $stateParams de sus padres, por lo que no se necesita una ''solución'' real.

Simplemente inyecte $stateParams como de costumbre en sus controladores secundarios y tendrá acceso completo a los parámetros que se están pasando. Si no desea utilizar los parámetros en un estado secundario específico, simplemente evite inyectarlos.

Esto funciona con;

  • Botón de retroceso
  • Botón de avance
  • ui-sref (sin params (se mantendrá como está))
  • ui-sref (con params (sobrescribirá))

$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 } } })

Si en algún momento desea borrar los parámetros mientras viaja dentro del árbol de estado del parent , tendrá que hacerlo manualmente.

Esa sería la única advertencia real que puedo ver al usar esta solución.

Me doy cuenta de que la limpieza manual puede no ser deseable en el caso de su presentación, pero no ha tomado una postura activa en contra de ella, por lo que creo que la sugerencia tiene mérito.

plunker actualizado