AngularJS UI-Router get the current state from within a view
-
21-12-2019 - |
Question
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.
Solution
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
OTHER TIPS
You can access the current state configuratin object like this:
$state.current
For further information take a look at the $state documentation.
You can do it as follow,
$state.current.name //Return the name of current state
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
This is useful if you are looking for Current state name, $state.current.name
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
A working "out of the box" Controller from your code, which shows state:
.controller('State1Ctrl', function ($state) {
console.log("Current State: ", $state.current.name);
});
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)