Jak wysyłać i pobierać parametry za pomocą $ state.go toParams i $ stateParams?

123

Używam AngularJS v1.2.0-rc.2 z ui-router v0.2.0. Chcę przekazać stan strony odsyłającej do innego stanu, więc używam znaku toParamsof $state.gotak:

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

Według dokumentacji powinno to wypełnić pole $stateParamsna toStatekontrolerze, ale tak jest undefined. czego mi brakuje?

Stworzyłem plunk, aby zademonstrować:

http://plnkr.co/edit/ywEcG1

gwhn
źródło

Odpowiedzi:

147

Jeśli chcesz przekazać stan bez adresu URL, nie możesz używać urlpodczas konfigurowania state. Znalazłem odpowiedź na PR i trochę małpowałem, aby lepiej zrozumieć.

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

Następnie możesz przejść do niego w następujący sposób:

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

Lub:

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

A zatem w HTML:

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

Ten przypadek użycia jest całkowicie ujawniony w dokumentacji, ale myślę, że jest to potężny sposób na przejście do stanu bez użycia adresów URL.

brązowy
źródło
2
UWAGA: (w wersji 0.2.10) Jeśli stan jest stanem potomnym elementu nadrzędnego, który ma parametr adresu URL, to parametr ten musi zostać uwzględniony w paramstablicy.
ivarni
5
Otrzymałem komunikat o błędzie „Brak wymaganego parametru”, gdy wymieniłem parametry jako tablicę w definicji stanu. Zamiast tego {referer: true, param2: true, etc: true}
wymień
1
To nie zadziałało dla mnie w najnowszej wersji v0.2.13. Być może nie bez powodu było to udokumentowane.
demisx
1
W najnowszej wersji musisz zmienić parametry, aby były obiektem. więc params: {myParam: {value: defaultValue / undefined }}
rbnzdave
2
jak mogę uzyskać dane w kontrolerze?
Shylendra Madda
47

Rozwiązanie Nathana Matthewsa nie zadziałało dla mnie, ale jest całkowicie poprawne, ale nie ma sensu szukać obejścia:

Kluczowa kwestia to: Typ definiowanych parametrów i toParamas z $ state.go powinny być tą samą tablicą lub obiektem po obu stronach przejścia stanów.

Na przykład, kiedy definiujesz parametry w stanie w następujący sposób, oznacza to, że params jest tablicą, ponieważ używasz "[]":

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

Więc również powinieneś przekazać toParams jako tablicę w następujący sposób:

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

Możesz uzyskać do nich dostęp poprzez $ stateParams w postaci tablicy w następujący sposób:

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

Lepszym rozwiązaniem jest użycie obiektu zamiast tablicy po obu stronach :

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

Zastąpiłem [] {} w definicji params. Aby przekazać toParams do $ state.go również powinieneś użyć object zamiast array:

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

wtedy możesz łatwo uzyskać do nich dostęp przez $ stateParams:

app.controller('overviewController', function($scope, $stateParams) {
    var index = $stateParams.index;
    var anotherKey = $stateParams.anotherKey;
});
Reza Rahimi
źródło
Zdecydowanie działa i wykorzystałem go w swoim projekcie. Czy to przetestowałeś? Daj mi znać o problemie, jeśli go przetestujesz.
Reza Rahimi
1
to nie jest format obiektu {'index', 'anotherKey'} jak to działa? Spróbowałem. To nie zadziałało.
maxisam
Umieść fragment kodu, wersję lub coś, co może pomóc w rozwiązaniu problemu. Użyłem tych wersji: AngularJS v1.2.26, ui-router v0.2.11, CoffeeScript, również użyłem ich wersji bower.
Reza Rahimi
3
to działa, ale zastępując params: {'index', 'anotherKey'},w params: {'index' : 'dummy', 'anotherKey' : 'dummy'},przeciwnym razie to nie jest poprawnym obiektem javascript
ps0604
28

Wszystko, co musiałem zrobić, to dodać parametr do definicji stanu adresu URL w ten sposób

url: '/toState?referer'

No!

gwhn
źródło
Jedynym sposobem, w jaki mogę to uruchomić ze /toState/:refererskładnią, jest użycie $location.path()zamiast $state.go().
siostrzeniec
Nie znalazłeś innego rozwiązania wykorzystującego funkcjonalność ui-routera?
Jason,
istnieje sposób, aby to działało z $ state.go (). Zajęło mi trochę czasu, zanim zrobiłem to dobrze. Zobacz mój przykład tutaj.
mbokil
Zadziałało. Jednak może nie być jasne, co zrobić, jeśli chcesz przekazać dwa parametry; więc poniższy wiersz załatwia sprawę. url: "/ contact? myParam1 & myParam2"
eduardo92
15

Nie jestem pewien, czy będzie działać z AngularJS v1.2.0-rc.2 z ui-router v0.2.0. Przetestowałem to rozwiązanie na AngularJS v1.3.14 z ui-router v0.2.13.

Po prostu zdaję sobie sprawę, że nie jest konieczne przekazywanie parametru w adresie URL, jak zaleca gwhn.

Po prostu dodaj parametry z wartością domyślną w definicji stanu. Twój stan może nadal mieć wartość adresu URL.

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

i dodaj parametr do $state.go()

$state.go('state1',{new_param: "Going places!"});
Phyxius
źródło
Jak udokumentowano tutaj: Używanie parametrów bez
określania
Coll ... Uratowaliście mój dzień, ludzie! Proste i bezpośrednie rozwiązanie.
Nowdeen
15

Żaden z tych przykładów na tej stronie nie zadziałał dla mnie. To jest to, czego użyłem i działało dobrze. Niektóre rozwiązania mówią, że nie można łączyć url z $ state.go (), ale to nieprawda. Niezręczne jest to, że musisz zdefiniować parametry dla adresu URL, a także wymienić parametry. Obie muszą być obecne. Testowane na Angular 1.4.8 i UI Router 0.2.15.

w stanie dodaj parametry do końca stanu i zdefiniuj parametry:

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

W Twoim kontrolerze instrukcja go będzie wyglądać następująco:

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

Następnie wyciągnij parametry i użyj ich w kontrolerze nowego stanu (nie zapomnij przekazać $ stateParams do funkcji kontrolera):

var index = $stateParams.index;
var anotherKey = $stateParams.anotherKey;
console.log(anotherKey); //it works!
mbokil
źródło
11

W moim przypadku próbowałem ze wszystkimi podanymi tutaj opcjami, ale nikt nie działał poprawnie (angular 1.3.13, ionic 1.0.0, angular-ui-router 0.2.13). Rozwiązaniem było:

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

i w stanie. go:

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

Twoje zdrowie

Cris R
źródło
U mnie to działało dobrze, pod warunkiem, że kontroler przestrzega parametru o tej samej nazwie, na przykład $ stateParams.param1.
nuander
tak @nuander, zapomniałem wspomnieć o tym, jak uzyskać dostęp do tej zmiennej, dzięki za to!
Cris R,
8

Spędziłem dużo czasu walcząc z $ state & $ stateParams; Ionic / Angular;

Aby użyć $ state.go () i $ stateParams, musisz mieć pewne ustawienia, a inne parametry nie mogą być obecne.

W mojej app.config () zawarłem $ stateProvider i zdefiniowałem w nim kilka stanów:

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

paramsKluczem jest szczególnie ważne. Jak dobrze, zauważ, że nie maurl kluczy ... wykorzystując stateParams i adresy URL NIE mieszają się. One wzajemnie się wykluczają.

W wywołaniu $ state.go () zdefiniuj to następująco:

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

Te indexi anotherKeyzmienne $ stateParams będzie tylko być wypełniane, jeżeli są one najpierw wymienione w $ stateControllerparams określającego klucz.

W kontrolerze uwzględnij $ stateParams, jak pokazano na ilustracji:

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

Przekazywane zmienne powinny być dostępne!

Nathan Matthews
źródło
Czy wartość może być obiektem JSON? Na przykład $ state.go ('view', {'editObj': {wart1: 2, wart2: 3, wart4: 'Witaj'}}). Ponieważ to nie działa dla mnie.
PavanSandeep
6

Spróbuj z reload: true ?

Najdłużej nie mogłem zrozumieć, co się dzieje - okazuje się, że oszukiwałem siebie. Jeśli jesteś pewien, że wszystko jest napisane poprawnie i będziesz chciał używać tego samego stanu, spróbuj reload: true:

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

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

Mam nadzieję, że to oszczędza czas!

Cody
źródło
5

Miałem podobny problem. Skończyło się na działającym rozwiązaniu po wielu googlach, próbach i testach. Oto moje rozwiązanie, które będzie dla Ciebie odpowiednie.

Mam dwa kontrolery - searchBoxController i stateResultController oraz parametr o nazwie searchQuery który ma być przekazany z widoku posiadającego pole wyszukiwania do widoku pokazującego wyniki pobrane ze zdalnego serwera. Tak to się robi:

Poniżej znajduje się kontroler, z którego wywołujesz następny widok za pomocą $state.go()

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

Poniżej znajduje się stan, który zostanie wywołany, gdy $state.go()zostanie wykonany:

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

I na koniec kontroler powiązany ze app.searchResultsstanem:

.controller('stateResultController', function ($scope, $state, $stateParams, $http) {
        $scope.searchQueryInput = $stateParams.searchQuery;
    });
Azharullah Shariff
źródło
1
To zadziałało dla mnie i było dokładnie tym, czego potrzebowałem, ponieważ nie chciałem przekazywać parametru w adresie URL, ale potrzebowałem właściwości url w deklaracji stanu.
Ernani
3

A w moim przypadku stanu rodzic / dziecko. wszystkie parametry zadeklarowane w stanie potomnym muszą być znane przez stan nadrzędny

        .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'
                }
            }
        })
cynk
źródło
2

Rozwiązanie, do którego doszliśmy, gdy stan przyjmował 2 parametry, zmieniało się:

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

do

.state('somestate', {
  url: '/somestate?id=:&sub=:',
  views: {...}
}
Seth Caldwell
źródło
1

Zdefiniuj następujące w router.js

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

Twój kontroler musi dodać $ stateParams.

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

Możesz wysłać obiekt za pomocą parametru w następujący sposób.

$state.go('users', {obj:yourObj});
MahmutKarali
źródło
1

Próbowałem przejść ze strony 1 do 2 i musiałem również przekazać pewne dane.

W moim routerze.js dodałem nazwę i wiek parametrów :

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

W Strona1 , onClick następnego przycisku:

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

Na stronie 2 mogłem uzyskać dostęp do tych parametrów:

$stateParams.name
$stateParams.age
Praveesh P.
źródło