Exposing the current state name with ui router

104,538

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


imgur

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);
    });

  }
})();
Share:
104,538
motleydev
Author by

motleydev

Updated on July 28, 2022

Comments

  • motleydev
    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
    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
    nikjohn over 8 years
    Why do the $rootScope.$state = $state; $rootScope.$stateParams = $stateParams; though?
  • rnrneverdies
    rnrneverdies over 8 years
    @ChanandlerBong To make it globally available at any scope.
  • Angelin
    Angelin over 7 years
    It's already globally available by injecting it where it's needed. No need to use $rootScope for it.
  • rnrneverdies
    rnrneverdies over 7 years
    @Angelin If you need to explicitly inject it everywhere you need it, so is not "already globally available" XD.
  • Michiel
    Michiel over 7 years
    This 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
    Kirkland over 7 years
    You can omit the delay... $timeout(function() { console.log($state.current); });
  • bsm
    bsm almost 4 years
    This now works <a ui-sref="{ language: 'de' }">de</a> see: ui-router.github.io/ng1/docs/latest/modules/…