I want to get the value of one of the properties in the $stateParams object in my controller. I seem to be able to get the $stateParams object as a whole but I can't get a specific property.
$rootScope.params = $stateParams; // this gets me the object
$rootScope.myVar = $stateParams.fooParam + ' some msg'; // this gets me undefined
So this is how I setup my $stateProvider...
$stateProvider
.state('parent', {
url: "/parent",
templateUrl: 'tpl.html',
params: {
fooParam: 'foo defult',
barParam: 'bar defult'
},
controller: 'ParentCtrl'
})
And then in my html ui-sref route, I pass some stuff to the param.
<a ui-sref="parent({
fooParam:'foo parent',
barParam:'bar parent'
})">parent</a>
Then in my controller I want to access those params. Here is where Is truggle to access members of the $stateParams object.
$rootScope.myVar = $stateParams.fooParam + ' some msg';
In my HTML if I call {{myVar}}, I just get "undefined some msg"
Basically in this particular example I want to get the value of the fooParam in my controller. I don't understand how to do that.
Here's a Plunker of the example of my issue:
https://plnkr.co/edit/dXTgKMpBTHiv2Bt5nFxC?p=preview
Actually, I was wrong. You do need to include params in the url as below:
$stateProvider
.state('parent', {
url: "/parent/:fooParam/:barParam",
params: {
fooParam: 'foo defult',
barParam: 'bar defult'
},
templateUrl: 'tpl.html',
controller: 'ParentCtrl'
})
But the other issue is that you need to access $stateParams from the controller registered for that state, which is listed in the gotchas section of the documentation.
See updated plunker showing myVar from $stateParams injected in controller (works fine) and MyVar2 from $stateParams injected in app.run() function (doesn't work).
You can inject $stateParams directly into controller. Change your controller as below.
.controller('ParentCtrl', ['$scope','$stateParams', function($scope,$stateParams)
Here is the Plunker
https://plnkr.co/edit/PVXGjFLMVQdvxUHp1rgs?p=preview
Related
Is it possible to automatically set a $scope value in a controller from a state definition?
For example, if I have state definition
$stateProvider.state("page", {
url: "/page", controller: PageController, template: "<div></div>"
}
And I navigate to page with a parameter like this:
$state.go("page", {param1: 'value1'});
Is it possible to inject param1 in PageController $scope using the state definition to be able to call $scope.param1 in PageController and give me the value 'value1'?
Obviously, I can just set it in the PageController with
$scope.param1 = $stateParams.param1;
But I'm looking to see if I can include this as part of state definition instead (like in the resolve maybe).
Try this :
routing :
.state('page', {
url: '/page',
template: '<div></div>',
controller: 'PageController',
data : {param1 : 'value1'}
})
PostController :
controller('PageController', function($state, $scope){
console.log($state.current.data.param1);
})
I have a stateProvider which looks like:
$stateProvider.state('test.example', {
url: '/test?param1¶m2',
templateUrl: 'test/testParam.html',
controller: 'testParamCtrl'
});
When I console log $stateParams in my controller, it runs twice. This happens only when I'm switching between tabs on my app. This problem doesn't occur if I refresh the app.
It seems as if the controller is "building" the stateParams object and instantiating the controller each time. Therefore, I'm getting some angular errors of param2 being undefined during the first instantiation. This is what the console logs look like:
Object {param1: "data1", param2: undefined} // first instantiation
Object {param1: "data1", param2: "data2"} // second instantiation
When I refresh the page, however, only one console log shows up, which is the "correct one" (i.e. param1 and param2 are both defined).
Thanks in advance!
My guess is that in 'test/testParam.html' you have ng-controller="testParamCtrl". Remove ng-controller in the template or remove the controller property in your state definition.
I think you need to change your state defination to:
$stateProvider.state('test.example', {
url: '/test/:param1/:param2',
templateUrl: 'test/testParam.html',
controller: 'testParamCtrl'
});
to pass parameters in the right way.
You need to assign parameter values
$stateProvider.state('test.example', {
url: '/test/:param1/:param2',
params: {
param1: "data1",
param2: "data2" }
templateUrl: 'test/testParam.html',
controller: 'testParamCtrl'});
Given the following state in ui-router:
.state('some.state', {
url: '/some/:viewType',
templateUrl: 'myTemplate.html',
controller: 'SomeStateController',
controllerAs: 'vm',
data: {
authorizedFor: [SOME_ROLE]
}
}
I'm trying to use the "data" object for a state to help control access to authorized states. Separately, I handle the $stateChangeStart event to look at data.authorizedFor and act accordingly.
The problem, though, is that the list of authorized roles might change based on the value of :viewType. I thought I could let data:{} be a function, inject $stateParams, and handle the logic there...but that won't do.
So, I tried using the params object instead, but at the $stateChangeStart time, the :viewType is not yet accessible from $state.params or $stateParams.
Stepping through in dev tools, I noticed that $state.transitionTo.arguments is populated, but it seems awfully hacky to go that route.
params: {
authorizedFor: function($state) {
console.log($state.transitionTo.arguments[1].viewType); // has value I need
}
}
Any suggestions?
My suggestion is to use resolve to provide your controller with content or data that is custom to the state. resolve is an optional map of dependencies which should be injected into the controller.
If any of these dependencies are promises, they will be resolved and converted to a value before the controller is instantiated and the $stateChangeSuccess event is fired.
for example:
$stateProvider
.state('profile', {
url: '/profile',
templateUrl: 'profile.html',
resolve:{
'ProfileService': function(ProfileService){
return ProfileService.promise_skillRecommendation_mock;
}
}
})
The profileService code:
var app = angular.module('app').service("ProfileService", function($http){
var myData = null;
var promise_skillRecommendation_mock =
$http.get('Mock/skillRecommendation-mock.json')
.success(function(data){
myData = data;
});
return{
promise_skillRecommendation_mock: promise_skillRecommendation_mock,
get_skillRecommendation: function(){
return myData;
}
};
});
and the controller code which will use this service is:
angular.module('app').controller('ProfileController', function($scope, $http, ProfileService){
$scope.skillRecommendation = ProfileService.get_skillRecommendation();
The object in resolve below must be resolved (via deferred.resolve() if they are a promise) before the controller is instantiated. Notice how each resolve object is injected as a parameter into the controller.
by using this code, the page will be displayed only after that the promise will be resolved.
for more info please view this page: https://github.com/angular-ui/ui-router/wiki
I'm trying to route to a url with the selected object's id value within a nested state but it's not working.
ROUTER:
.state('sessions.editor', {
url: '/editor/:id',
templateUrl: 'views/editor.html',
controller: 'EditorCtrl'
})
CONTROLLER (EditorCtrl):
$scope.theSession.$id = $stateParams.id;
//$scope.session object is successfully returned with the $id property.
PREVIOUS CONTROLLER:
//when button is clicked
$state.go('sessions.editor');
However, when I try to set it to $stateParams, the id property becomes undefined. I tested this with another property on $scope.session and that property becomes undefined also when I try to set it $stateParams.
I'm thinking the trouble has something to do with the state being nested. Is this correct?
I believe you need to add the params key to the state for UI-Router, example:
.state('sessions.editor', {
url: '/editor/:id',
controller: 'EditorCtrl',
templateUrl: 'views/editor.html',
params: {
id: {
value : '',//Default
squash: false
}
}
})
Then use your existing implementation in the EditorCtrl for $stateParams.
I have these routes defined:
.state('sport',
url: '/sport'
templateUrl: '/templates/sport'
controller: 'SportCtrl'
)
.state('sport.selected'
url: '/:sport'
templateUrl: '/templates/sport'
controller: 'SportCtrl'
)
And I have this controller trying to use the :sport param given by sport.selected state.
angular.module('myApp')
.controller('SportCtrl', ['$scope', 'ParseService',
'$stateParams', function ($scope, ParseService, $stateParams) {
var sportURL = $stateParams.sport;
...
});
For some reason, it returns undefined when I call $stateParams.sport in the controller, even though I think I defined it in the routes.
Why is this the case?
Thanks for your help!
When you access the URL /sport/12, the SportCtrl will be instantiated twice: once for the state sport, and once for the state sport.selected. And for the first state, there is no parameter associated with the state, so $stateParams.sport is undefined.
Note that it's quite strange to use the same template for a state and a sub-state. You'll have the template embedded inside the ui-view div of the same template.