¿Cómo enviar y recuperar parámetros usando $ state.go toParams y $ stateParams?

123

Estoy usando AngularJS v1.2.0-rc.2 con ui-router v0.2.0. Quiero pasar el estado de referencia a otro estado, así que uso el toParamsde $state.goigual manera:

$state.go('toState', {referer: $state.current.name});

De acuerdo con los documentos , esto debería llenar $stateParamsel toStatecontrolador, pero lo es undefined. ¿Qué me estoy perdiendo?

He creado un plunk para demostrar:

http://plnkr.co/edit/ywEcG1

gwhn
fuente

Respuestas:

147

Si desea pasar un estado que no sea URL, no debe usarlo urlal configurar su state. Encontré la respuesta en un RP e hice algunos monos para entender mejor.

$stateProvider.state('toState', {
  templateUrl:'wokka.html',
  controller:'stateController',
  params: {
    'referer': 'some default', 
    'param2': 'some default', 
    'etc': 'some default'
  }
});

Luego puedes navegar hacia ella así:

$state.go('toState', { 'referer':'jimbob', 'param2':37, 'etc':'bluebell' });

O:

var result = { referer:'jimbob', param2:37, etc:'bluebell' };
$state.go('toState', result);

Y en HTML así:

<a ui-sref="toState(thingy)" class="list-group-item" ng-repeat="thingy in thingies">{{ thingy.referer }}</a>

Este caso de uso está completamente descubierto en la documentación, pero creo que es un medio poderoso para la transición del estado sin usar URL.

bbrown
fuente
2
NOTA: (en v0.2.10) Si el estado es un estado hijo de un padre que tiene un parámetro de URL, entonces ese parámetro debe incluirse en la paramsmatriz.
ivarni
55
Recibí un error que decía "Falta el parámetro requerido" cuando enumeré los parámetros como una matriz en la definición de estado. En su lugar, {referer: true, param2: true, etc: true}
enumérelos
1
Esto no funcionó para mí en la última v0.2.13. Tal vez, fue indocumentado por una razón.
Demisx
1
En la última versión, debe cambiar los parámetros para ser un objeto. por lo params: {myParam: {valor: defaultValue / indefinido }}
rbnzdave
2
¿Cómo puedo obtener los datos en el controlador?
Shylendra Madda
47

La solución de Nathan Matthews no funcionó para mí, pero es totalmente correcta, pero no tiene mucho sentido llegar a una solución alternativa:

El punto clave es: Tipo de parámetros definidos y toParamas de $ state.go debe ser la misma matriz u objeto en ambos lados de la transición de estado.

Por ejemplo, cuando define los parámetros en un estado de la siguiente manera, significa que los parámetros son una matriz debido al uso de "[]":

$stateProvider
.state('home', {
    templateUrl: 'home',
    controller:  'homeController'
})
.state('view', {
    templateUrl: 'overview',
    params:      ['index', 'anotherKey'],
    controller:  'overviewController'
})

Por lo tanto, también debe pasar aParams como una matriz como esta:

params = { 'index': 123, 'anotherKey': 'This is a test' }
paramsArr = (val for key, val of params)
$state.go('view', paramsArr)

Y puede acceder a ellos a través de $ stateParams como una matriz como esta:

app.controller('overviewController', function($scope, $stateParams) {
    var index = $stateParams[0];
    var anotherKey = $stateParams[1];
});

Una mejor solución es usar un objeto en lugar de una matriz en ambos lados :

$stateProvider
.state('home', {
    templateUrl: 'home',
    controller:  'homeController'
})
.state('view', {
    templateUrl: 'overview',
    params:      {'index': null, 'anotherKey': null},
    controller:  'overviewController'
})

Reemplacé [] con {} en la definición de parámetros. Para pasar toParams a $ state.go también debe usar object en lugar de array:

$state.go('view', { 'index': 123, 'anotherKey': 'This is a test' })

entonces puede acceder a ellos a través de $ stateParams fácilmente:

app.controller('overviewController', function($scope, $stateParams) {
    var index = $stateParams.index;
    var anotherKey = $stateParams.anotherKey;
});
Reza Rahimi
fuente
Definitivamente funciona y lo he usado en mi proyecto. ¿Lo probaste? Déjame saber el problema, si lo pruebas.
Reza Rahimi el
1
no es un formato de objeto {'index', 'anotherKey'} ¿cómo puede funcionar esto? Lo intenté No funcionó.
maxisam
Ponga su fragmento de código, versión o algo que pueda ayudar a resolver el problema. He usado estas versiones: AngularJS v1.2.26, ui-router v0.2.11, CoffeeScript también he usado la versión de Bower de ellas.
Reza Rahimi
3
esto funciona, sin embargo, reemplazarlo params: {'index', 'anotherKey'},de lo params: {'index' : 'dummy', 'anotherKey' : 'dummy'},contrario no es un objeto javascript válido
ps0604
28

Todo lo que tenía que hacer era agregar un parámetro a la definición del estado de la URL de esta manera

url: '/toState?referer'

Doh!

gwhn
fuente
La única forma en que puedo hacer que esto funcione con la /toState/:referersintaxis es usar en $location.path()lugar de $state.go().
nshew
¿No encontró ninguna otra solución con la funcionalidad de ui-router?
Jason
hay una manera de hacer que esto funcione con $ state.go (). Me tomó algo de tiempo para hacerlo bien. Mira mi ejemplo aquí.
mbokil
Funcionó. Sin embargo, puede que no esté claro qué sucede si desea pasar dos parámetros; entonces la siguiente línea hace el truco. url: "/ contactos? myParam1 y myParam2"
eduardo92
15

No estoy seguro de si funcionará con AngularJS v1.2.0-rc.2 con ui-router v0.2.0. He probado esta solución en AngularJS v1.3.14 con ui-router v0.2.13.

Me doy cuenta de que no es necesario pasar el parámetro en la URL como recomienda gwhn.

Simplemente agregue sus parámetros con un valor predeterminado en su definición de estado. Su estado aún puede tener un valor de URL.

$stateProvider.state('state1', {
    url : '/url',
    templateUrl : "new.html",
    controller : 'TestController',
    params: {new_param: null}
});

y agregue el parámetro a $state.go()

$state.go('state1',{new_param: "Going places!"});
Phyxius
fuente
Coll ... ¡Me salvaste el día, hombres! Solución simple y directa.
Nowdeen 01 de
15

Ninguno de estos ejemplos en esta página funcionó para mí. Esto es lo que usé y funcionó bien. Algunas soluciones dicen que no se puede combinar la URL con $ state.go () pero esto no es cierto. Lo incómodo es que debe definir los parámetros para la url y también enumerar los parámetros. Ambos deben estar presentes. Probado en Angular 1.4.8 y UI Router 0.2.15.

En el estado, agregue sus parámetros al final del estado y defina los parámetros:

url: 'view?index&anotherKey',
params: {'index': null, 'anotherKey': null}

En su controlador, su declaración go se verá así:

$state.go('view', { 'index': 123, 'anotherKey': 'This is a test' });

Luego, para extraer los parámetros y usarlos en el controlador de su nuevo estado (no olvide pasar $ stateParams a la función de su controlador):

var index = $stateParams.index;
var anotherKey = $stateParams.anotherKey;
console.log(anotherKey); //it works!
mbokil
fuente
11

En mi caso, probé con todas las opciones dadas aquí, pero nadie funcionaba correctamente (angular 1.3.13, iónico 1.0.0, angular-ui-router 0.2.13). La solución fue:

.state('tab.friends', {
      url: '/friends/:param1/:param2',
      views: {
        'tab-friends': {
          templateUrl: 'templates/tab-friends.html',
          controller: 'FriendsCtrl'
        }
      }
    })

y en el estado.

$state.go('tab.friends', {param1 : val1, param2 : val2});

Salud

Cris R
fuente
Esto funcionó bien para mí, siempre que el controlador reverenciara el parámetro con el mismo nombre, por lo que $ stateParams.param1, por ejemplo.
nuander
sí @nuander, olvidé mencionar cómo acceder a esa variable, ¡gracias por eso!
Cris R
8

He pasado mucho tiempo luchando con los $ state & $ stateParams de Ionic / Angular;

Para utilizar $ state.go () y $ stateParams, debe tener ciertas cosas configuradas y otros parámetros no deben estar presentes.

En mi app.config () he incluido $ stateProvider y he definido varios estados:

$stateProvider
    .state('home', {
        templateUrl: 'home',
        controller:  'homeController'
    })
    .state('view', {
        templateUrl: 'overview',
        params:      ['index', 'anotherKey'],
        controller:  'overviewController'
    })

La paramsclave es especialmente importante. Además, observe que NO hay urlclaves presentes ... utilizando stateParams y las URL NO se mezclan. Son mutuamente excluyentes entre sí.

En la llamada $ state.go (), defínalo como tal:

$state.go('view', { 'index': 123, 'anotherKey': 'This is a test' })

Las variables indexy anotherKey$ stateParams SOLO se completarán si se enumeran por primera vez en la paramsclave de definición $ stateController .

Dentro del controlador, incluya $ stateParams como se ilustra:

app.controller('overviewController', function($scope, $stateParams) {
    var index = $stateParams.index;
    var anotherKey = $stateParams.anotherKey;
});

¡Las variables pasadas deberían estar disponibles!

Nathan Matthews
fuente
¿Puede el valor ser un objeto JSON? Como $ state.go ('ver', {'editObj': {val1: 2, val2: 3, val4: 'Hola'}}). Porque esto no funciona para mí.
PavanSandeep
6

Probar con reload: true?

No pude entender lo que estaba pasando durante mucho tiempo, resulta que me estaba engañando a mí mismo. Si está seguro de que las cosas están escritas correctamente y usará el mismo estado, intente reload: true:

.state('status.item', {
    url: '/:id',
    views: {...}
}

$state.go('status.item', { id: $scope.id }, { reload: true });

Espero que esto te ahorre tiempo!

Cody
fuente
5

Me enfrenté a un problema similar. Terminé con una solución de trabajo después de mucho googlear y probar y probar. Aquí está mi solución que funcionaría para usted.

Tengo dos controladores: searchBoxController y stateResultController y un parámetro llamado searchQuery para pasar de una vista que tiene un cuadro de búsqueda a una vista que muestra los resultados obtenidos de un servidor remoto. Así es como lo haces:

A continuación se muestra el controlador desde el que se llama a la siguiente vista usando $state.go()

.controller('searchBoxController', function ($scope, $state) {
        $scope.doSearch = function(){
            var searchInputRaw = $scope.searchQueryInput;
            $state.go('app.searchResults', { searchQuery: searchInput });
        }
    })

A continuación se muestra el estado al que se llamaría cuando $state.go()se ejecute:

.state('app.searchResults', 
            {
                url: '/searchResults',
                views:
                {
                    'menuContent': { templateUrl: 'templates/searchResult.html', controller: 'stateResultController' }
                },
                params: 
                {
                    'searchQuery': ''
                }
            })

Y finalmente, el controlador asociado con el app.searchResultsestado:

.controller('stateResultController', function ($scope, $state, $stateParams, $http) {
        $scope.searchQueryInput = $stateParams.searchQuery;
    });
Azharullah Shariff
fuente
1
Esto funcionó para mí y era exactamente lo que necesitaba, ya que no quería pasar el parámetro en la URL, pero necesitaba la propiedad url en la declaración de estado.
Ernani
3

Y en mi caso de un estado padre / hijo. todos los parámetros declarados en estado hijo deben ser conocidos por el estado padre

        .state('full', {
            url: '/full',
            templateUrl: 'js/content/templates/FullReadView.html',
            params: { opmlFeed:null, source:null },
            controller: 'FullReadCtrl'
        })
        .state('full.readFeed', {
            url: '/readFeed',
            views: {
                'full': {
                    templateUrl: 'js/content/templates/ReadFeedView.html',
                    params: { opmlFeed:null, source:null },
                    controller: 'ReadFeedCtrl'
                }
            }
        })
zinc
fuente
2

La solución para llegar a tener un estado que tomara 2 parámetros estaba cambiando:

.state('somestate', {
  url: '/somestate',
  views: {...}
}

a

.state('somestate', {
  url: '/somestate?id=:&sub=:',
  views: {...}
}
Seth Caldwell
fuente
1

Su siguiente definición en router.js

$stateProvider.state('users', {
    url: '/users',
    controller: 'UsersCtrl',
    params: {
        obj: null
    }
})

Su controlador necesita agregar $ stateParams.

function UserCtrl($stateParams) {
    console.log($stateParams);
}

Puede enviar un objeto por parámetro de la siguiente manera.

$state.go('users', {obj:yourObj});
MahmutKarali
fuente
1

Intenté navegar de la página 1 a la 2 y tuve que pasar algunos datos también.

En mi router.js , agregué el nombre y la edad de los parámetros :

.state('page2', {
          url: '/vehicle/:source',
          params: {name: null, age: null},
.................

En la Página 1 , onClick del botón a continuación:

$state.go("page2", {name: 'Ron', age: '20'});

En la página 2 , pude acceder a esos parámetros:

$stateParams.name
$stateParams.age
Praveesh P
fuente