Como enviar e recuperar parâmetros usando $ state.go toParams e $ stateParams?

123

Estou usando o AngularJS v1.2.0-rc.2 com o ui-router v0.2.0. Eu quero passar o estado de referência para outro estado para que eu use o toParamsda $state.goseguinte forma:

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

De acordo com os documentos , isso deve preencher o $stateParamsno toStatecontrolador, mas é undefined. o que estou perdendo?

Eu criei um plunk para demonstrar:

http://plnkr.co/edit/ywEcG1

gwhn
fonte

Respostas:

147

Se você deseja passar o estado que não é da URL, não deve usá-lo urlao configurar o seu state. Encontrei a resposta em um PR e fiz algumas pesquisas para entender melhor.

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

Então você pode navegar para ele da seguinte maneira:

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

Ou:

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

E em HTML assim:

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

Esse caso de uso é completamente descoberto na documentação, mas acho que é um meio poderoso de fazer a transição do estado sem usar URLs.

bbrown
fonte
2
NOTA: (na v0.2.10) Se o estado for um estado filho de um pai que possui um parâmetro de URL, esse parâmetro precisará ser incluído na paramsmatriz.
Ivarni
5
Eu estava recebendo um erro dizendo "Falta parâmetro obrigatório" quando listei os parâmetros como uma matriz na definição de estado. Em vez disso, liste-os como um hash{referer: true, param2: true, etc: true}
Dave Ceddia
1
Isso não funcionou para mim na versão v0.2.13 mais recente. Talvez não tenha sido documentado por um motivo.
demisx
1
No mais recente, você precisa alterar os parâmetros para ser um objeto. so params: {myParam: {value: defaultValue / undefined }}
rbnzdave
2
como posso obter os dados no controlador?
Shylendra Madda
47

A solução de Nathan Matthews não funcionou para mim, mas é totalmente correta, mas há pouco sentido em chegar a uma solução alternativa:

O ponto principal é: O tipo de parâmetros definidos e os toParamas de $ state.go devem ser o mesmo array ou objeto nos dois lados da transição de estado.

Por exemplo, quando você define um parâmetro no estado da seguinte maneira, significa que o parâmetro é matriz por usar "[]":

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

Então você também deve passar paraParams como um array como este:

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

E você pode acessá-los via $ stateParams como uma matriz como esta:

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

Uma solução melhor é usar objeto em vez de matriz nos dois lados :

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

Substituí [] por {} na definição de parâmetros. Para passar toParams para $ state.go, você também deve usar object em vez de array:

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

então você pode acessá-los via $ stateParams facilmente:

app.controller('overviewController', function($scope, $stateParams) {
    var index = $stateParams.index;
    var anotherKey = $stateParams.anotherKey;
});
Reza Rahimi
fonte
Definitivamente funciona e eu usei no meu projeto. Você testou? Deixe-me saber o problema, se você testá-lo.
Reza Rahimi
1
não é um formato de objeto {'index', 'anotherKey'} como isso pode funcionar? Eu tentei. Não deu certo.
Maxisam #
Coloque seu snippet de código, versão ou algo que possa ajudar a resolver o problema. Eu usei estas versões: AngularJS v1.2.26, ui-router v0.2.11, CoffeeScript também usei a versão do bower.
Reza Rahimi
3
isso funciona, no entanto, substituir params: {'index', 'anotherKey'},por params: {'index' : 'dummy', 'anotherKey' : 'dummy'},outro não é um objeto javascript válido
ps0604
28

Tudo o que eu precisava fazer era adicionar um parâmetro à definição do estado da URL, assim

url: '/toState?referer'

Doh!

gwhn
fonte
A única maneira de conseguir que isso funcione com /toState/:referersintaxe é usar em $location.path()vez de $state.go().
Nshew
Você não encontrou nenhuma outra solução usando a funcionalidade do ui-router?
23414 Jason
existe uma maneira de fazer isso funcionar com $ state.go (). Levei algum tempo para acertar. Veja meu exemplo aqui.
mbokil
Funcionou. No entanto, pode não estar claro o que se você deseja passar dois parâmetros; então a seguinte linha faz o truque. url: "/ contatos? myParam1 e myParam2"
eduardo92
15

Não tenho certeza se funcionará com o AngularJS v1.2.0-rc.2 com o ui-router v0.2.0. Testei esta solução no AngularJS v1.3.14 com o ui-router v0.2.13.

Acabei de perceber que não é necessário passar o parâmetro na URL, como recomenda a gwhn.

Basta adicionar seus parâmetros com um valor padrão na sua definição de estado. Seu estado ainda pode ter um valor de URL.

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

e adicione o parâmetro a $state.go()

$state.go('state1',{new_param: "Going places!"});
Phyxius
fonte
Coll ... Você salvou meu dia homens! Solução simples e direta.
Nowdeen 01/04/19
15

Nenhum desses exemplos nesta página funcionou para mim. Isto é o que eu usei e funcionou bem. Algumas soluções disseram que você não pode combinar URL com $ state.go (), mas isso não é verdade. O estranho é que você deve definir os parâmetros para o URL e também listar os parâmetros. Ambos devem estar presentes. Testado no Angular 1.4.8 e no UI Router 0.2.15.

No estado, adicione seus parâmetros ao final do estado e defina os parâmetros:

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

No seu controlador, sua instrução go será assim:

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

Em seguida, retire os parâmetros e use-os no controlador do seu novo estado (não esqueça de passar $ stateParams para a função do controlador):

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

No meu caso, tentei com todas as opções fornecidas aqui, mas ninguém estava funcionando corretamente (angular 1.3.13, iônico 1.0.0, angular-ui-router 0.2.13). A solução foi:

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

e no state.go:

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

Felicidades

Cris R
fonte
Isso funcionou bem para mim, desde que o controlador reverencie o parâmetro com o mesmo nome, então $ stateParams.param1, por exemplo.
Nuander
yes @nuander, esqueci de mencionar como acessar essa variável, obrigado por isso!
Cris R
8

Passei bastante tempo lutando com o $ state & $ stateParams da Ionic / Angular;

Para utilizar $ state.go () e $ stateParams, você deve ter algumas coisas configuradas e outros parâmetros não devem estar presentes.

No meu app.config (), incluí o $ stateProvider e defini nele vários estados:

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

A paramschave é especialmente importante. Além disso, observe que NÃO há urlchaves presentes ... utilizando stateParams e URLs NÃO se misturam. Eles são mutuamente exclusivos.

Na chamada $ state.go (), defina-a da seguinte forma:

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

As variáveis indexe anotherKey$ stateParams SOMENTE serão preenchidas se forem listadas pela primeira vez na paramschave de definição $ stateController .

Dentro do controlador, inclua $ stateParams conforme ilustrado:

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

As variáveis ​​passadas devem estar disponíveis!

Nathan Matthews
fonte
O valor pode ser um objeto JSON? Como $ state.go ('view', {'editObj': {val1: 2, val2: 3, val4: 'Hello'}}). Porque isso não está funcionando para mim.
PavanSandeep
6

Tente com reload: true?

Não conseguia descobrir o que estava acontecendo há mais tempo - eu estava me enganando. Se você tiver certeza de que as coisas foram escritas corretamente e usará o mesmo estado, tente reload: true:

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

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

Espero que isso economize seu tempo!

Cody
fonte
5

Eu tinha enfrentado um problema semelhante. Acabei com uma solução funcional depois de muito pesquisar, testar e testar. Aqui está a minha solução que funcionaria para você.

Eu tenho dois controladores - searchBoxController e stateResultController e um parâmetro chamado searchQuery a ser passado de uma exibição com uma caixa de pesquisa para uma exibição mostrando os resultados buscados em um servidor remoto. É assim que se faz:

Abaixo está o controlador a partir do qual você chama a próxima visualização usando $state.go()

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

Abaixo está o estado que seria chamado quando a $state.go()execução fosse :

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

E, finalmente, o controlador associado ao app.searchResultsestado:

.controller('stateResultController', function ($scope, $state, $stateParams, $http) {
        $scope.searchQueryInput = $stateParams.searchQuery;
    });
Azharullah Shariff
fonte
1
Isso funcionou para mim e era exatamente o que eu precisava, pois não queria passar o parâmetro na URL, mas precisava da propriedade url na declaração de estado.
Ernani
3

E no meu caso de um estado pai / filho. todos os parâmetros declarados no estado filho devem ser conhecidos pelo estado pai

        .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
fonte
2

A solução que chegamos a ter um estado com dois parâmetros estava mudando:

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

para

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

Você define o seguinte em router.js

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

Seu controlador precisa adicionar $ stateParams.

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

Você pode enviar um objeto por parâmetro da seguinte maneira.

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

Eu estava tentando navegar da página 1 para a 2 e também precisava passar alguns dados.

No meu router.js , adicionei nome e idade dos parâmetros :

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

Na Página1 , clique no botão Avançar:

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

Em Page2 , eu poderia acessar esses parâmetros:

$stateParams.name
$stateParams.age
Praveesh P
fonte