I am passing a value from one state to another using UI-Router. In my controller when the url is updated I am trying to get access to the second parameter of my url using $stateParams, but for some reason I can get access to the first parameter but the second one is UNDEFINED. This is my code:
state 1, URL:
http://localhost:16009/#/5nqeAPqlv21/
state 2, URL:
http://localhost:16009/#/5nqeAPqlv21/details/PP163Ku3dOR
candidateContoller.js:
//go to state 2 (same controller for parent and child views)
$state.go('index.details', { "submissionIdd": publicSubmissionId });
//when located in the new state and new url:
console.log($stateParams.submissionIdd); //shows undefined
console.log($stateParams.token); //shows 5nqeAPqlv21
App.js:
$stateProvider
.state('index',
{
url: '/:token/',
views: {
'': {
templateUrl: 'AngularJS/Templates/indexView.html',
controller: 'candidateController as candCtrl'
},
'sectioncandidate#index': {
templateUrl: (_isNotMobile)
? 'AngularJS/Templates/candidatesView.html'
: 'AngularJS/Templates/candidatesMobileView.html'
}
}
})
.state('index.details', {
url: 'details/{submissionIdd}',
views: {
'sectioncandidate#index': {
templateUrl: (_isNotMobile)
? 'AngularJS/Templates/candidateView.html'
: 'AngularJS/Templates/candidateMobileView.html'
}
}
})
You do experience standard behavior of the UI-Router and Parent/Child state defintion:
parent state declares $stateParams (as url: '/:token/') - so there is just one declared - a token
child state gets all from parent(s), plus declares new parameter (as url: 'details/{submissionIdd}') - so it has both defined - token and submissionIdd,
So, while child has access to both params, parent state has just a token parameter
state 1 === PARENT, URL:
http://localhost:16009/#/5nqeAPqlv21/
here we will have submissionIdd undefined
state 2 === CHILD, URL:
http://localhost:16009/#/5nqeAPqlv21/details/PP163Ku3dOR
both are there submissionIdd=PP163Ku3dOR and token=5nqeAPqlv21
Extend - there is a working plunker
This states definition (in the plunker a bit adjusted)
.state('index',
{
url: '/:token/',
views: {
'': {
templateUrl: 'indexView.html',
controller: 'candidateController as candCtrl'
},
'sectioncandidate#index': {
templateUrl: 'parent.html'
}
}
})
.state('index.details', {
url: 'details/{submissionIdd}',
views: {
'sectioncandidate#index': {
templateUrl:'child.html',
}
})
will properly show state params for these links
href
<a href="#/5nqeAPqlv21/">
<a href="#/5nqeAPqlv21/details/PP163Ku3dOR">
<a href="#/5nqeAPqlv21/details/other">
ui-sref
<a ui-sref="index({token: '5nqeAPqlv21'})">
<a ui-sref="index.details({token: '5nqeAPqlv21', submissionIdd: 'another'})">
Check it here
You can prefer not to pass the the params in the URL unless there is an explicit requirement. I would prefer to use $stateParams in controller to fetch the data.
For this you need to define the default params in the state to
make it work.
$stateProvider .state('index.details', {
url: 'details',
params: {
submissionIdd: 'default',
},
views: {
'sectioncandidate#index': {
templateUrl: (_isNotMobile) ? 'AngularJS/Templates/candidateView.html' : 'AngularJS/Templates/candidateMobileView.html' ,
controller: function($stateParams){
console.log($stateParams.submissionIdd)
}
}
}
})
Related
I have to open the new tab using state.go with parameter,
State config:
.state("view", {
url: "/view",
templateUrl: 'app/components/view/view.html',
controller: 'viewController',
params: {
data: ''
}
})
In the some controller:
var url = $state.href('view', {data: JSON.stringify($scope.data)});
window.open(url,'_blank');
When i tried above code its redirecting to new tab but i can't able to get the passed params values in the viewcontroller.
In your controller you have to inject $stateParams like
.state("view", {
url: "/view/:data",
templateUrl: 'app/components/view/view.html',
controller: 'viewController'
})
.controller('viewController', ['$stateParams', function($stateParams) {
$scope.params = $stateParams.data; // here you get parameter values
})
I have one parent state and child states for that parent. Parent state have one optional parameter reviewId. Everything is working good, when I am sending parameter in $state.go state is opened correctly. What I need is to append (add that optional query parametar in url) when creating new review (id is populated after making back end call).
This is url for opening existing review with id:
http://localhost:3000/#/planning?reviewId=1000.
When creating new review url is:
http://localhost:3000/#/planning. So what I need is after review is saved (Id is populated) to append ?reviewId=newId without state.go.
$stateProvider
.state('root.planning', {
url: '/planning?reviewId=',
abstract: true,
params: {
reviewId: null,
readOnlyMode: null,
locked: null,
editButton: null
},
reloadOnSearch:false,
views: {
'#': {
templateUrl: 'src/app/modules/planning/views/planning.tpl.html',
controller: 'PlanningMainController as reviewvm'
}
}
})
.state('root.planning.planning', {
url: '',
params: {
reviewId: null
},
data: {
planningChild: true,
stateTypeCd : "PLA"
},
reloadOnSearch:false,
templateUrl: 'src/app/modules/planning/views/tabs/tab.planning.view.html',
controller: 'PlanningController as planningvm'
})
EDIT
Tried also to update reviewId in stateParams after Id is accessed and then call $state.reload(). With this approach stateParams.reviewId is null after reload. And I was wondering if I can do this without reload.
$stateProvider
.state('root.planning', {
url: '/planning?reviewId',
abstract: true,
controller: function($scope, $stateParams) {
$scope.reviewId = $stateParams.reviewId;
}
call the function if $statePrams.reviewId is available. hope this will help you
This should be simple but I just can't figure it out.
I have two routes:
$stateProvider
.state('users', {
url: '/users',
views: {'#': {
templateUrl: 'templates/users.tpl.html',
controller: 'UsersCtrl as users'
}}
})
.state('users.edit', {
url: '/{userId}',
views: {'#': {
templateUrl: 'templates/editUser.tpl.html',
controller: 'EditUserCtrl as editUser'
}}
});
This works fine if you use a ui-sref or $state.go to navigate to the "users" state by name, but if you type domain.com/users/ into the URL bar it goes to the edit state with empty userId parameter even though there is nothing after the trailing stash.
Normally this wouldn't be a problem but firing the editUser route with no userId causes console errors which would be a pain to fix.
Is this easily fixable?
Take a look to this post:
https://github.com/angular-ui/ui-router/issues/50
and this link referenced in the post:
https://github.com/angular-ui/ui-router/wiki/Frequently-Asked-Questions#how-to-make-a-trailing-slash-optional-for-all-routes
Your states definition should be
$stateProvider
.state('users', {
url: '/users',
views: {'#': {
templateUrl: 'templates/users.tpl.html',
controller: 'UsersCtrl as users'
}}
})
.state('users.edit', {
url: '/edit/{userId}',
views: {'#': {
templateUrl: 'templates/editUser.tpl.html',
controller: 'EditUserCtrl as editUser'
}}
});
your child state url should be '/edit/{userId}'. When we create a child state its url automatically added its parent state url. So if your url is '/{userId}' it will be 'domain.com/users/{userId}'. That's why for domain.com/users/ its navigate to the state users.edit with null parameter value.
https://github.com/angular-ui/ui-router/wiki/nested-states-%26-nested-views
My question is simple, but I couldn't find solution anywhere else.
For example I have a normal route state with parameter,
.state('page', {
url: '/page/:pageid',
templateUrl: 'templates/pages.html',
controller: 'pagesCtrl'
})
However for example, if I have 1000 pages, but for the Number 1 and Number 999 pages I have to use another template. How could I simply do this? Something like
.state('page', {
url: '/page/:pageid',
templateUrl: 'templates/pages.html',
controller: 'pagesCtrl'
})
.state('page', {
url: '/page/1',
templateUrl: 'templates/page1.html',
controller: 'pagesCtrl'
})
.state('page', {
url: '/page/999',
templateUrl: 'templates/page999.html',
controller: 'pagesCtrl'
})
Will this work?I tested, the later 2 options are not overriding the original state with parameter.
If I wish to use the same controller, how to load the 1 and the 999 as the pageid parameter in the controller?
Definitely you shouldn't have two more state for separate template. You should use single generic state which will take templateUrl with the help of passed state parameter.
Code
.state('page', {
url: '/page/:id',
templateUrl: function($stateParams){
var template = $stateParams.id.indexOf([1, 1000]) > -1?'pages.html'
:'page'+$stateParams.id+'.html';
return 'templates/'+template ,
}
controller: 'pagesCtrl'
})
I have this in my app.js:
$stateProvider
.state('actionplans', {
url: "/actionplans",
templateUrl: "pages/actionplans.html",
//controller : 'ActionplansCtrl'
})
.state('actionplans.planning', {
url: "/planning",
templateUrl: "pages/actionplans.planning.html",
//controller : 'ActionplansCtrl'
})
.state('actionplans.summary', {
url: "/summary",
templateUrl: "pages/actionplans.summary.html",
//controller : 'ActionplansCtrl'
})
How can I default load nest view action 'actionplans.summary.html' when called actionplans.html?
There is a working example
The way which will
load some view inside of a parent - and stay on parent
allow child change it when navigating to child
is called Multiple named views:
.state('actionplans', {
url: "/actionplans",
views: {
'': {
templateUrl: "pages/actionplans.html",
//controller : 'ActionplansCtrl'
},
'#actionplans': {
templateUrl: "pages/actionplans.summary.html",
//controller : 'ActionplansCtrl'
}
}
})
.state('actionplans.planning', {
url: "/planning",
templateUrl: "pages/actionplans.planning.html",
//controller : 'ActionplansCtrl'
})
.state('actionplans.summary', {
url: "/summary",
templateUrl: "pages/actionplans.summary.html",
//controller : 'ActionplansCtrl'
})
What we did above, is that we used views : {} object to define two views. First is targeting the index.html (the '') the second is targeting this state view target for children ( the '#actionplans').
views: {
'': { // index.html
...
},
'#actionplans': { // this targets the unnamed view for children
Read more about absolute names here
Another way, is to define some default redirection, but that will disable parent state as a real target (e.g. here Redirect a state to default substate with UI-Router in AngularJS)
Here discuss about AngularJS Routing Using UI-Router, you will get enough idea about nested view and multiple view.
https://scotch.io/tutorials/angular-routing-using-ui-router
I found a simple solution here.
$urlRouterProvider.when('/actionplans', '/actionplans/summary');//<-- Add in this line
$stateProvider
.state('actionplans', {
url: "/actionplans",
abstract: true,/// <-- Add in this line
templateUrl: "pages/actionplans.html",
})
.state('actionplans.planning', {
url: "/planning",
templateUrl: "pages/actionplans.planning.html",
})
.state('actionplans.summary', {
url: "/summary",
templateUrl: "pages/actionplans.summary.html",
})
This will load nest view actionplans.summary.html by default when you call /actionplans. My apology that I did not make this clearer in my question so I post the answer here hopefully it will help someone else with the similar scenario.