Comment envoyer et récupérer des paramètres en utilisant $ state.go toParams et $ stateParams?

123

J'utilise AngularJS v1.2.0-rc.2 avec ui-router v0.2.0. Je veux passer l'état du référent à un autre état, donc j'utilise le toParamsof $state.golike so:

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

Selon la documentation , cela devrait remplir le $stateParamssur le toStatecontrôleur, mais c'est le cas undefined. Qu'est-ce que je rate?

J'ai créé un plunk pour démontrer:

http://plnkr.co/edit/ywEcG1

gwhn
la source

Réponses:

147

Si vous souhaitez transmettre un état non URL, vous ne devez pas l'utiliser urllors de la configuration de votre state. J'ai trouvé la réponse sur un PR et j'ai fait quelques singes pour mieux comprendre.

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

Ensuite, vous pouvez y accéder comme suit:

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

Ou:

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

Et en HTML donc:

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

Ce cas d'utilisation est complètement découvert dans la documentation, mais je pense que c'est un moyen puissant de transition d'état sans utiliser d'URL.

brun
la source
2
REMARQUE: (sur v0.2.10) Si l'état est un état enfant d'un parent qui a un paramètre URL, alors ce paramètre doit être inclus dans le paramstableau.
ivarni
5
J'obtenais une erreur indiquant "Paramètre requis manquant" lorsque j'ai répertorié les paramètres sous forme de tableau dans la définition d'état. Au lieu de cela, {referer: true, param2: true, etc: true}
listez-
1
Cela n'a pas fonctionné pour moi dans la dernière v0.2.13. Peut-être que c'était sans papiers pour une raison.
demisx
1
Dans la dernière version, vous devez changer les paramètres pour devenir un objet. so params: {myParam: {value: defaultValue / undefined }}
rbnzdave
2
comment puis-je obtenir les données dans le contrôleur?
Shylendra Madda
47

La solution de Nathan Matthews n'a pas fonctionné pour moi, mais elle est tout à fait correcte mais il n'y a pas grand intérêt à trouver une solution de contournement:

Le point clé est: Le type de paramètres définis et toParamas de $ state.go doit être le même tableau ou objet des deux côtés de la transition d'état.

Par exemple, lorsque vous définissez un paramètre dans un état comme suit, vous voulez dire que params est un tableau en raison de l'utilisation de "[]":

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

Vous devez donc également passer toParams en tant que tableau comme celui-ci:

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

Et vous pouvez y accéder via $ stateParams en tant que tableau comme celui-ci:

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

La meilleure solution consiste à utiliser un objet au lieu d'un tableau des deux côtés :

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

J'ai remplacé [] par {} dans la définition des paramètres. Pour passer toParams à $ state.go, vous devez également utiliser object au lieu de array:

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

alors vous pouvez y accéder facilement via $ stateParams:

app.controller('overviewController', function($scope, $stateParams) {
    var index = $stateParams.index;
    var anotherKey = $stateParams.anotherKey;
});
Reza Rahimi
la source
Cela fonctionne vraiment et je l'ai utilisé dans mon projet. L'avez-vous testé? Faites-moi savoir le problème, si vous le testez.
Reza Rahimi
1
ce n'est pas un format d'objet {'index', 'anotherKey'} comment cela peut-il fonctionner? J'ai essayé. Ça n'a pas marché.
maxisam
Mettez votre extrait de code, votre version ou quelque chose qui peut aider à résoudre le problème. J'ai utilisé ces versions: AngularJS v1.2.26, ui-router v0.2.11, CoffeeScript également J'en ai utilisé la version de bower.
Reza Rahimi
3
cela fonctionne, mais en remplaçant params: {'index', 'anotherKey'},par params: {'index' : 'dummy', 'anotherKey' : 'dummy'},sinon ce n'est pas un objet javascript valide
ps0604
28

Tout ce que j'avais à faire était d'ajouter un paramètre à la définition de l'état de l'url comme ceci

url: '/toState?referer'

Doh!

gwhn
la source
La seule façon de faire fonctionner cela avec la /toState/:referersyntaxe est d'utiliser à la $location.path()place de $state.go().
nshew
Vous n'avez trouvé aucune autre solution utilisant les fonctionnalités de ui-router?
Jason
il existe un moyen de faire fonctionner cela avec $ state.go (). Il m'a fallu du temps pour bien faire les choses. Voir mon exemple ici.
mbokil
Ça a marché. Cependant, ce n'est peut-être pas clair si vous voulez passer deux paramètres; donc la ligne suivante fait l'affaire. url: "/ contacts? myParam1 & myParam2"
eduardo92
15

Je ne sais pas si cela fonctionnera avec AngularJS v1.2.0-rc.2 avec ui-router v0.2.0. J'ai testé cette solution sur AngularJS v1.3.14 avec ui-router v0.2.13.

Je réalise juste qu'il n'est pas nécessaire de passer le paramètre dans l'URL comme le recommande gwhn.

Ajoutez simplement vos paramètres avec une valeur par défaut sur votre définition d'état. Votre état peut toujours avoir une valeur URL.

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

et ajoutez le paramètre à $state.go()

$state.go('state1',{new_param: "Going places!"});
Phyxius
la source
Coll ... Vous avez sauvé mon jour les hommes! Solution simple et directe.
Nowdeen
15

Aucun de ces exemples sur cette page n'a fonctionné pour moi. C'est ce que j'ai utilisé et cela a bien fonctionné. Certaines solutions disent que vous ne pouvez pas combiner url avec $ state.go () mais ce n'est pas vrai. La chose gênante est que vous devez définir les paramètres de l'url et également lister les paramètres. Les deux doivent être présents. Testé sur Angular 1.4.8 et UI Router 0.2.15.

Dans l' état, ajoutez vos paramètres à la fin de l'état et définissez les paramètres:

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

Dans votre contrôleur, votre instruction go ressemblera à ceci:

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

Ensuite, pour extraire les paramètres et les utiliser dans le contrôleur de votre nouvel état (n'oubliez pas de passer $ stateParams à votre fonction de contrôleur):

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

Dans mon cas, j'ai essayé avec toutes les options données ici, mais personne ne fonctionnait correctement (angular 1.3.13, ionic 1.0.0, angular-ui-router 0.2.13). La solution était:

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

et dans le state.go:

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

À votre santé

Cris R
la source
Cela a bien fonctionné pour moi, à condition que le contrôleur vénère le paramètre du même nom, donc $ stateParams.param1 par exemple.
nuander
oui @nuander, j'ai oublié de mentionner comment accéder à cette variable, merci pour ça!
Cris R
8

J'ai passé beaucoup de temps à me battre avec $ state & $ stateParams;

Pour utiliser $ state.go () et $ stateParams, vous devez avoir configuré certaines choses et d'autres paramètres ne doivent pas être présents.

Dans mon app.config (), j'ai inclus $ stateProvider et défini en son sein plusieurs états:

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

La paramsclé est particulièrement importante. De plus, notez qu'il n'y a AUCUNE urlclé présente ... en utilisant stateParams et les URL ne se mélangent PAS. Ils s'excluent mutuellement.

Dans l'appel $ state.go (), définissez-le comme tel:

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

Les variables indexet anotherKey$ stateParams seront UNIQUEMENT remplies si elles sont d'abord répertoriées dans la paramsclé de définition $ stateController .

Dans le contrôleur, incluez $ stateParams comme illustré:

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

Les variables passées devraient être disponibles!

Nathan Matthews
la source
La valeur peut-elle être un objet JSON? Comme $ state.go ('view', {'editObj': {val1: 2, val2: 3, val4: 'Hello'}}). Parce que cela ne fonctionne pas pour moi.
PavanSandeep
6

Essayez avec reload: true?

Je n'arrivais pas à comprendre ce qui se passait depuis le plus longtemps - je me trompais. Si vous êtes certain que les choses sont écrites correctement et que vous allez utiliser le même état, essayez reload: true:

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

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

J'espère que cela vous fera gagner du temps!

Cody
la source
5

J'étais confronté à un problème similaire. Je me suis retrouvé avec une solution fonctionnelle après beaucoup de recherches sur Google et d'essais et de tests. Voici ma solution qui fonctionnerait pour vous.

J'ai deux contrôleurs - searchBoxController et stateResultController et un paramètre nommé searchQuery à passer d'une vue ayant une zone de recherche à une vue montrant les résultats extraits d'un serveur distant. Voici comment procéder:

Vous trouverez ci-dessous le contrôleur à partir duquel vous appelez la vue suivante en utilisant $state.go()

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

Voici l'état qui serait appelé lorsque le $state.go()est exécuté:

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

Et enfin, le contrôleur associé à l' app.searchResultsétat:

.controller('stateResultController', function ($scope, $state, $stateParams, $http) {
        $scope.searchQueryInput = $stateParams.searchQuery;
    });
Azharullah Shariff
la source
1
Cela a fonctionné pour moi et c'était exactement ce dont j'avais besoin, car je ne voulais pas passer le paramètre dans l'URL mais j'avais besoin de la propriété url dans la déclaration d'état.
Ernani le
3

Et dans mon cas, un état parent / enfant. tous les paramètres déclarés dans l'état enfant doivent être connus par l'état parent

        .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'
                }
            }
        })
zinking
la source
2

La solution que nous avons trouvée pour avoir un état qui prenait 2 paramètres était en train de changer:

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

à

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

Votre définition suivante dans router.js

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

Votre contrôleur doit ajouter $ stateParams.

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

Vous pouvez envoyer un objet par paramètre comme suit.

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

J'essayais de naviguer de la page 1 à la page 2 et je devais également transmettre certaines données.

Dans mon router.js , j'ai ajouté le nom et l' âge des paramètres :

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

Dans Page1 , surCliquez sur le bouton suivant:

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

Dans Page2 , je pourrais accéder à ces paramètres:

$stateParams.name
$stateParams.age
Praveesh P
la source