Exposing the current state name with ui router
Solution 1
this is how I do it
JAVASCRIPT:
var module = angular.module('yourModuleName', ['ui.router']);
module.run( ['$rootScope', '$state', '$stateParams',
function ($rootScope, $state, $stateParams) {
$rootScope.$state = $state;
$rootScope.$stateParams = $stateParams;
}
]);
HTML:
<pre id="uiRouterInfo">
$state = {{$state.current.name}}
$stateParams = {{$stateParams}}
$state full url = {{ $state.$current.url.source }}
</pre>
EXAMPLE
http://plnkr.co/edit/LGMZnj?p=preview
Solution 2
Answering your question in this format is quite challenging.
On the other hand you ask about navigation and then about current $state
acting all weird.
For the first I'd say it's too broad question and for the second I'd say... well, you are doing something wrong or missing the obvious :)
Take the following controller:
app.controller('MainCtrl', function($scope, $state) {
$scope.state = $state;
});
Where app
is configured as:
app.config(function($stateProvider) {
$stateProvider
.state('main', {
url: '/main',
templateUrl: 'main.html',
controller: 'MainCtrl'
})
.state('main.thiscontent', {
url: '/thiscontent',
templateUrl: 'this.html',
controller: 'ThisCtrl'
})
.state('main.thatcontent', {
url: '/thatcontent',
templateUrl: 'that.html'
});
});
Then simple HTML template having
<div>
{{ state | json }}
</div>
Would "print out" e.g. the following
{
"params": {},
"current": {
"url": "/thatcontent",
"templateUrl": "that.html",
"name": "main.thatcontent"
},
"transition": null
}
I put up a small example showing this, using ui.router
and pascalprecht.translate
for the menus. I hope you find it useful and figure out what is it you are doing wrong.
Plunker here http://plnkr.co/edit/XIW4ZE
Screencap
Solution 3
In my current project the solution looks like this:
I created an abstract Language State
$stateProvider.state('language', {
abstract: true,
url: '/:language',
template: '<div ui-view class="lang-{{language}}"></div>'
});
Every state in the project has to depend on this state
$stateProvider.state('language.dashboard', {
url: '/dashboard'
//....
});
The language switch buttons calls a custom function:
<a ng-click="footer.setLanguage('de')">de</a>
And the corresponding function looks like this (inside a controller of course):
this.setLanguage = function(lang) {
FooterLog.log('switch to language', lang);
$state.go($state.current, { language: lang }, {
location: true,
reload: true,
inherit: true
}).then(function() {
FooterLog.log('transition successfull');
});
};
This works, but there is a nicer solution just changing a value in the state params from html:
<a ui-sref="{ language: 'de' }">de</a>
Unfortunately this does not work, see https://github.com/angular-ui/ui-router/issues/1031
Solution 4
Use Timeout
$timeout(function () { console.log($state.current, 'this is working fine'); }, 100);
See - https://github.com/angular-ui/ui-router/issues/1627
Solution 5
I wrapped around $state
around $timeout
and it worked for me.
For example,
(function() {
'use strict';
angular
.module('app')
.controller('BodyController', BodyController);
BodyController.$inject = ['$state', '$timeout'];
/* @ngInject */
function BodyController($state, $timeout) {
$timeout(function(){
console.log($state.current);
});
}
})();
motleydev
Updated on July 28, 2022Comments
-
motleydev almost 2 years
I'm trying to implement a language switcher where if a user clicks on "de" from any given page on an "en" side - it takes them to that page of the "de" side. If I console.dir the $state parameter, it exposes the values I'd want with the "current" property of the given $state. If I try to console.dir the $state.current to focus on the values I want, it only gives the parent state property (my current views are nested).
My current thinking is, I'm on url/en/content, and dynamically I can then have my lang navigation dynamically load the appropriate destination points into some kind of data attribute, pick those up with a custom directive where I'd initiate a "go to" and set my preferedLanguage value per angular-translate.
The key issue at the moment is exposing that $state name - again, when simply browsing $state the current object gives the values I'd want, but $current.state directly only gives the parent state.
If anyone has a better suggestion of how to do this (in a angular way - no custom cookie junk) I'm happy to take suggestions.
Thanks!
Update! CODE SAMPLES:
Object reference of my states:
var urlStates = { en: { home: { name: 'home', url: '/en', templateUrl: 'templates/'+lang+'/home.html', abstract: 'true' }, home_highlights: { name:'home.highlights', url: '', templateUrl: 'templates/'+lang+'/home.highlights.html' }, home_social: { name: 'home.social', url: '/social', templateUrl: 'templates/'+lang+'/home.social.html' }, home_map: { name: 'home.map', url: '/map', templateUrl: 'templates/'+lang+'/home.map.html' } };
My States:
$stateProvider .state(urlStates.en.home) .state(urlStates.en.home_highlights) .state(urlStates.en.home_social) .state(urlStates.en.home_map); $locationProvider.html5Mode(true); })
Controller:
.controller('LandingPage', function($translate, $state){ this.state = $state; this.greeting = "Hello"; });
And Lastly, the output I see in the dom:
With this.state = $state;
{ "params": {}, "current": { "name": "home.highlights", "url": "", "templateUrl": "templates/en/home.highlights.html" }, "transition": null }
With this.state = $state.current
{ "name": "", "url": "^", "views": null, "abstract": true }
-
motleydev almost 10 years"you are doing something wrong or missing the obvious" - a very wise deduction from the state of my question. :) I'm trying to figure this out here. I am updating my answer with some code examples. The problem is, When I pass the $state object to the front end - I see that my ideal value lives at $state.current.name - if I try to access that, say, send that specific value to the front end with $state.value.name I get the name of the parent state not the nested state. But - enough talk, see above again for some code. :)
-
nikjohn over 8 yearsWhy do the
$rootScope.$state = $state; $rootScope.$stateParams = $stateParams;
though? -
rnrneverdies over 8 years@ChanandlerBong To make it globally available at any scope.
-
Angelin over 7 yearsIt's already globally available by injecting it where it's needed. No need to use $rootScope for it.
-
rnrneverdies over 7 years@Angelin If you need to explicitly inject it everywhere you need it, so is not "already globally available" XD.
-
Michiel over 7 yearsThis only worked for me when I set my timeout to about 500 ms, under 200ms console logs something else like in original question. This seems a fuzzy solution to me, even though it works
-
Kirkland over 7 yearsYou can omit the delay...
$timeout(function() { console.log($state.current); });
-
bsm almost 4 yearsThis now works
<a ui-sref="{ language: 'de' }">de</a>
see: ui-router.github.io/ng1/docs/latest/modules/…