27

Considering the following states taken from the ui-router documentation:

.state('state1', {
  url: '/state1',
  templateUrl: 'partials/state1.html'
  controller: 'State1Ctrl'
})
.state('state1.list', {
  url: '/list',
  templateUrl: 'partials/state1.list.html',
})

And the controller for "partials/state1.html" for state "state1":

.controller('State1Ctrl', function () {

});

Is there any built-in feature to determine from within the controller or within the template, what state the controller/template is associated with?

For example:

.controller('State1Ctrl', function ($state) {
  console.log($state.this); // state1
});

And if there is no built-in solution, how would you "decorate" $state or $stateParams, to contain this information?

The only solution I've come up with is to use $state.get() and then find the state with the controller or template value. This seems incredibly messy, though.

Yennefer
  • 5,704
  • 7
  • 31
  • 44
TaylorMac
  • 8,882
  • 21
  • 76
  • 104

8 Answers8

71

You can access the current state configuratin object like this:

$state.current

For further information take a look at the $state documentation.

Himmet Avsar
  • 1,531
  • 16
  • 23
  • 1
    Current state will show $scope.current === 'state1.list' inside of 'State1Ctrl', not $scope.current = 'state1' IF the state is 'state1.list'. $state.current is always the current state, not the state bound to the controller. – TaylorMac Jul 30 '14 at 15:34
  • 2
    In ionic1 is actually `$state.current.name` - but nevertheless thank you for help – dannydedog Aug 03 '18 at 14:05
  • Its blank when just hit the page – Raz Buchnik Nov 20 '19 at 06:50
33

You can do it as follow,

$state.current.name //Return the name of current state
Gaurav Gandhi
  • 3,041
  • 2
  • 27
  • 40
10

Couldn't find this documented anywhere, so I looked in the source code.

There is a data field named $uiView attached to the ui-view element, it contains the view name and the associated state. You can get this state like this:

elem.closest('[ui-view]').data('$uiView').state

or even

elem.inheritedData('$uiView').state
cipak
  • 1,414
  • 1
  • 14
  • 20
  • 2
    Wow, thank you. The documentation is very fragmented and incomplete in my opinion, strange for such a widely used tool. Awesome – TaylorMac Oct 05 '14 at 20:53
  • 3
    does not seems like angular-way. You are trying to access dom element directly. Its jQuery way. – Rahul Prasad Feb 29 '16 at 17:55
  • 1
    @RahulPrasad you're right. It's not the Angular Way. But it's the Only Way:) – cipak Mar 21 '17 at 13:49
  • In ui-router 1.0+, things have changed a little. This works for me: `elem.inheritedData('$uiView').$cfg.viewDecl.$context`. The state data is also available in `$cfg.path`, which is what ui-sref uses when it makes links. See the `stateContext` function: https://github.com/angular-ui/ui-router/blob/1.0.13/src/directives/stateDirectives.ts#L36 – Chad von Nau Jan 25 '18 at 18:48
  • @ChadvonNau I am trying to convert from angular 1 to angular 2+. My angular 1 is using this code. is there way to convert to angular 2+? – learntech Jun 01 '22 at 20:04
5

We can see what is defined for current state, using the $state.current, check this example showing:

state1
{
  "url": "/state1",
  "template": "<div>state1 <pre>{{current | json }}</pre><div ui-view=\"\"></div> </div>",
  "controller": "State1Ctrl",
  "name": "state1"
}
list
{
  "url": "/list",
  "template": "<div>list <pre>{{current | json }}</pre></div>",
  "controller": "State1Ctrl",
  "name": "state1.list"
}

the controller:

.controller('State1Ctrl', function($scope, $state) {

  $scope.current = $state.current

});

check that here

EXTEND: The above example will always return current state - i.e. if there is hierarchy of three states and we access the last state ('state1.list.detail') directly:

<a ui-sref="state1.list.detail({detailId:1})">....

Each controller will be provided with the same state: $state("state1.list.detail").

Why? beause this state has enough information what are all the views (hierarchically nested) and their controllers needed. We can observe that all in the

$state.$current // not .current

Quickly discussed here cite:

In addition, users can attach custom decorators, which will generate new properties within the state's internal definition. There is currently no clear use-case for this beyond accessing internal states (i.e. $state.$current), however, expect this to become increasingly relevant as we introduce additional meta-programming features.

BUT: there is NO way, how to get information from current controller instance, to which $state it belongs! Even any iterations, searching through some $state.get('stateName') will be unreliable, because simply there is no kept relation that way. One controller Class could be used for many views as different Instances. And also, from my experience, I do not remember any case, when I needed to know such information... wish now it is a bit more clear

Radim Köhler
  • 122,561
  • 47
  • 239
  • 335
  • See response to user2992420 below – TaylorMac Jul 30 '14 at 15:33
  • Please illustrate with a plunkr if you can :) I'm having a hard time implementing this in my own controller, thank you! – TaylorMac Jul 30 '14 at 15:40
  • Try giving the child state it's own controller: http://plnkr.co/edit/Czc5kGpCwsruUQe2EanZ?p=preview. This is the issue I am running into – TaylorMac Jul 30 '14 at 15:50
  • Actually, it doesn't matter. In your example it doesn't work either. Try navigating directly to /state1/list as soon as the page loads. It will show that /list is the "current" state in both controllers/templates. – TaylorMac Jul 30 '14 at 16:00
  • I realized that my expalnation was not accurate previously. And I also realized that you decided to trust some obvious but in fact not accurate answer. Maybe the extension above will help. Please understand me correctly...my only goal is to help and improve our understanding of that amazing tool ui-router (our I mean including me;) good luck – Radim Köhler Jul 31 '14 at 03:28
  • Thank you, I've found that it is important to know which state is associated with which controller when the controller is loaded in cases where you have a data model that is representative of the hierarchy of your views, and when you reuse controllers (which is good practice, but difficult if you cant determine the "context" of the controller as it relates to the state. This is a common OOP problem, that exists without a solution in ui-router). – TaylorMac Jul 31 '14 at 20:28
4

This is useful if you are looking for Current state name, $state.current.name

Abhijeet
  • 8,561
  • 5
  • 70
  • 76
2

Not sure it is the same version, but on 0.3.1 you can use this to get the current state:

$state.$current.name

And to perform a check:

$state.is('contact.details.item');

Documentation: https://ui-router.github.io/ng1/docs/0.3.1/index.html#/api/ui.router.state.$state

Marcos
  • 1,240
  • 10
  • 20
2

A working "out of the box" Controller from your code, which shows state:

.controller('State1Ctrl', function ($state) {
    console.log("Current State: ", $state.current.name);
});
Oleg
  • 21
  • 4
1

If you want to check the current state

console.log("state", $state.current)

If you want to check the name of the current state name

console.log("statename", $state.current.name)

shael
  • 41
  • 4