This is my code.
.state('appSetting.studentList', { url: '/student', views: { 'list#appSetting': { templateUrl: appUrl + '/Student/List', controller: 'StudentCtrl' } } })
.state('appSetting.studentList.details', { url: '/:studentId', views: { 'details#appSetting': { templateUrl: appUrl + '/Student/Edit', controller: 'StudentEditCtrl' } } })
.state('appSetting.employeeList', { url: '/employee', views: { 'list#appSetting': { templateUrl: appUrl + '/Employee/List', controller: 'EmployeeCtrl' } } })
.state('appSetting.employeeList.details', { url: '/:employeeId', views: { 'details#appSetting': { templateUrl: appUrl + '/Employee/Edit', controller: 'EmployeeEditCtrl' } } })
I have a add button on layout , when user click the add button call the following function.
$scope.gotoAdd = function () {
if ($state.current.name.indexOf(".details") == -1) {
$state.go($state.current.name + ".details")
}
else {
var paramId = $state.current.url.slice(2);
$state.go($state.current.name, ({ studentId: "", reload: true }));
}
};
In the above code working fine, but when open employee page user click add button i want to empty of employeeId parameter. I have number of links so if condition is using lengthy process. The above variable paramId dynamically changed (one time "studentId" , "employeeId" ,..............) depends on current state.
I tried the following code but not working because paramId contains string value
$state.go($state.current.name, ({ paramId: "", reload: true }));
Why are you putting the second parameter in '( )' in $state.go().
Try
$state.go($state.current.next, {}, {reload: true});
or
$state.go($state.current.next, {paramId: ""}, {reload: true});
$scope.gotoAdd = function () {
if ($state.current.name.indexOf(".details") == -1) {
$state.go($state.current.name + ".details")
}
else {
for (var prop in $stateParams) {
if ($stateParams.hasOwnProperty(prop)) {
$stateParams[prop] = '';
}
}
$state.go($state.current.name,$stateParams, { reload: true });
}
};
$state.go can take an inherit boolean parameter that serve exactly for this purpose.
As of UI router 0.2.15 -probably an old version, the documentation states
inherit - {boolean=true}, If true will inherit url parameters from current url.
In fact, it reset not only url parameters, but all $stateParams to their default, like what they are in state definition.
This will keep only state params as passed through the params object and all other are set to default or deleted.
$state.go('target.state', params, {inherit: false});
Related
I have a scenario, to handle the params. ( when param exist it will handled differently )
so, how can i keep 2 templates and use them according to the requirement? at present I am trying like this, which is not working at all.
any one help me?
my state with 2 template: ( please help me to correct )
.state('serialCreateCase', {
url: '/serialCreateCase?sn=',
views:{
"" : {
"templateUrl": 'app/login/loginWithSerial.html'
},
"?sn=" : {
"templateUrl": 'app/login/login.html'
}
}
})
here is the redirection with 2 scenarios: ( correct me if I am wrong )
if(!$rootScope.isUserLoggedIn && toParams.sn !== undefined ) {
console.log('dont take action', toState, toParams.sn );
$rootScope.canNavigate = true;
$state.go('serialCreateCase'); //works
$state.go('serialCreateCase', {sn:'1234'}); //not works
event.preventDefault();
return;
}
There is a working plunker
I would say that you need replace templateUrl with
Templates
TemplateUrl ...
templateUrl can also be a function that returns a url. It takes one preset parameter, stateParams, which is NOT
injected.
TemplateProvider
Or you can use a template provider function which can be injected, has access to locals, and must return template HTML,
like this...
There are more details and plunkers
Angular UI Router: decide child state template on the basis of parent resolved object
dynamic change of templateUrl in ui-router from one state to another
This I prefer the most
...
templateProvider: [$stateParams, '$templateRequest',
function($stateParams, templateRequest)
{
var tplName = "pages/" + $stateParams.type + ".html";
return templateRequest(tplName);
}
],
(check it here) because it uses also $templateRequest
EXTEND
There is a working plunker
this could be the state def
.state('serialCreateCase', {
url: '/serialCreateCase?sn',
views: {
"": {
templateProvider: ['$stateParams', '$templateRequest',
function($stateParams, templateRequest) {
var tplName = "app/login/loginWithSerial.html";
if($stateParams.sn){
tplName = "app/login/login.html";
}
return templateRequest(tplName);
}
]
},
}
});
what we really need is to always pass some value, as sn. So, these should be the calls:
// we need to pass some value, to be sure that there will be other than last
<a ui-sref="serialCreateCase({sn: null})">
// here is reasonable value
<a ui-sref="serialCreateCase({sn:'1234'})">
Check it here in action
use, $stateParams instead of toParams,
1) Deciding the template depending on the param(your requirement)
.state('serialCreateCase', {
url: '/serialCreateCase?sn=',
views: {
'': {
templateUrl: function(stateParams) {
var param = stateParams.sn
return (param == undefined) ? 'app/login/loginWithSerial.html' : 'app/login/login.html'
},
controller: 'myController',
}
}
})
You can check the stateParam using the parameter of templateUrl, and change the templates.
2) change the state depending on the param from controller.
This is a sample controller where you can check the state parameter and use the re directions as your wish.
allControllers.controller('myController', ['$scope','$rootScope','$state','$stateParams',
function($scope,$rootScope,$state,$stateParams) {
if(!$rootScope.isUserLoggedIn)
{
if($stateParams.sn !== undefined )
{
alert('dont take action', $stateParams.sn );
}
else
{
alert('You can redirect, no parameter present');
}
}
}
}])
I have a parent state with 3 child states. The parent state retrieves data using promises and returns resolved data in an object (named 'data') so it is accessible to controller and views. Some child states need the resolved parent data also to define their own object named data. But it seems that when transitioning from sibling states their resolves are never reached (a breakpoint in the corresponding state definition never gets hit).
In short: when transferring from state 'settings.account.person' to sibling state 'settings.account.password' I want the resolve statement to be executed. Currently it is not being hit at all...
States:
.state('settings.account', {
url: '/account'
,resolve: {
menu: ['menu','MenuService', function (menu,MenuService) {
return MenuService.retrieveSubMenuByParentUrl(menu,'/settings/account');
}],
account: ['UserManagementService',function(UserManagementService) {
return UserManagementService.account();
}],
data: ['menu',function (menu) {
return {menu:menu};
}]
}
,views: {
'setting#settings': {
templateUrl: '/app/components/settings/account/views/tabpanel.html'
,controller: 'AccountController'
}
}
})
.state('settings.account.person', {
url: '/person',
resolve: {
languages: ['APIService',function(APIService) {
return APIService.call(AppConfig.API_ENDPOINTS.language);
}],
data: ['menu','account','languages',function(menu,account,languages){
return {
menu: menu,
account: account,
languages: languages
};
}]
}
,views: {
'tabContent#settings.account': {
templateUrl: '/app/components/settings/account/views/person.html'
,controller: 'AccountController'
}
}
})
.state('settings.account.password', {
url: '/password'
,data: ['account',function(account){
return {
account: account
};
}]
,views: {
'tabContent#settings.account': {
templateUrl: '/app/components/settings/account/views/password.html'
,controller: 'AccountController'
}
}
})
.state('settings.account.delete', {
url: '/delete'
,data: ['account',function(account){
return {
id: account.id
};
}]
,views: {
'tabContent#settings.account': {
templateUrl: '/app/components/settings/account/views/deleteAccount.html'
,controller: 'AccountController'
}
}
})
Oops.. I see that in states 'settings.account.password' and 'settings.account.delete' I forgot half of the resolve block.... No wonder it doesn't get hit.
In Angular ui router, when $state.go("main.loadbalancer.readonly"); is ran after main.loadbalancer.readonly has been previously activated, my resolve: {} is not being evaulauted/executed. The resolve is simply bypassed..I have verified this with the console.log($state.current.data['deviceId']); not showing.
angular.module("main.loadbalancer", ["ui.bootstrap", "ui.router"]).config(function($stateProvider) {
return $stateProvider.state("main.loadbalancer", {
url: "device/:id",
views: {
"content#": {
templateUrl: "loadbalancer/loadbalancer.html",
controller: "LoadBalancerCtrl"
}
}
}).state("main.loadbalancer.vips", {
resolve: {
isDeviceReadOnly: function($state) {
console.log($state.current.data['deviceId']);
if (!$state.current.data['deviceId']) {
console.log("pimp");
$state.go("main.loadbalancer.readonly");
}
}
},
url: "/vips",
templateUrl: "loadbalancer/vip-table.html",
controller: "VipListCtrl"
}).state("main.loadbalancer.readonly", {
url: "/readonly",
templateUrl: "loadbalancer/readonly.html",
controller: "ReadonlyCtrl"
});
});
Controller code:
submit = function() {
$state.current.data = { deviceId: false };
return LoadBalancerSvc.searchDevice($scope.searchInput.value).get().then(function(lb) {
console.log(lb.ha_status);
if (lb.ha_status == "secondary") {
console.log("hi");
$state.current.data['deviceId'] = false;
$state.go("main.loadbalancer.readonly"); //WHEN THIS IS RAN A SECOND TIME
AFTER STATE HAS BEEN ACTIVE BEFORE
$state.deviceReadonly = true
} else {
$state.current.data['deviceId'] = lb.id;
$state.deviceReadonly = false;
SearchSvc.updateDeviceNumber(lb.id);
$state.go("main.loadbalancer.vips", {id: lb.id});
console.log("bye");
}
});
};
I can only guess that since main.loadbalancer.vips has been activated previously, then to ui router it means once resolved always resolved. How can I make it to where each time the state is activated with $state.go("main.loadbalancer.readonly") resolve will be evaluated?
Note: I have also tried $state.go("main.loadbalancer.readonly", { reload: true }); to no success.
It seems that 'transitionTo' works instead.
if (lb.ha_status == "secondary") {
$state.current.data['deviceId'] = false;
$state.transitionTo("main.loadbalancer.readonly", {}, { reload: true });
$state.deviceReadonly = true
}
These are my state definitions:
$stateProvider
.state('schoolyears', {
url: '/schoolyears',
templateUrl: '../views/schoolyears.html',
controller: 'SchoolyearsController'
})
.state('schoolyears.selected', {
url: '/:schoolyearId'
})
Inside the SchoolyearsController I call $state.go when the selection of a row in the datagrid changes:
$scope.myOptions = {
data: 'myData',
multiSelect: false,
selectedItems: [],
afterSelectionChange: function (rowItem) {
if (rowItem.selected) {
$state.go('schoolyears.selected({ schoolyearId:' + rowItem.entity.schoolyearId + '}');
}
}};
Nothing happens in the url because in my browser console I have this error:
Error: Could not resolve 'schoolyears.selected({ schoolyearId:43}' from state 'schoolyears'
What I want is that the url changes to:
/#/schoolyears/43
Why can I not change the url?
Inside the SchoolyearsController change:
afterSelectionChange: function (rowItem) {
if (rowItem.selected) {
$state.go('schoolyears.selected({ schoolyearId:' + rowItem.entity.schoolyearId + '}');
}
}};
to:
afterSelectionChange: function (rowItem) {
if (rowItem.selected) {
$state.go('schoolyears.selected',{ schoolyearId: rowItem.entity.schoolyearId });
}
}};
As $state.go can be overloaded with two parameters in this instance, for more information please see the api reference
I have the following set up:
var admin = {
name: 'admin',
url: '/admin',
views: {
'menu': {
templateUrl: '/Content/app/admin/partials/menu.html',
},
'content': {
templateUrl: function (stateParams) {
var content = localStorage.getItem('ls.adminPage');
if (content != null && content != "") {
return '/Content/app/admin/partials/' + content + '.html';
} else {
return '/Content/app/common/partials/empty.html';
}
}
}
}
};
var adminContent = {
name: 'admin.content',
parent: 'admin',
url: '/:content',
views: {
'content#': {
templateUrl: function (stateParams) {
localStorage.setItem('ls.adminPage', stateParams.content);
return '/Content/app/admin/partials/' + stateParams.content + '.html';
},
}
}
}
What happens is that when a user has previously been to the /admin/xxx page then the next time /admin is selected it will again return the /admin/xxx page.
However visually this is a mess as the browser URL shows as /admin and the state is not set correctly.
Is there some way I can store away a child state and then have it so that when the user browses to the parent that it will transition to the last known child state and have that URL show in the browswer ?
Do this:
myapp.config(function($urlRouterProvider){
$urlRouterProvider.when('/admin', function() {
var content = localStorage.getItem('ls.adminpage');
if ( content != null && content != "" ) {
return "/admin/" + content;
}
else {
return false;
}
});
});
See this plunkr: http://plnkr.co/edit/oEXZpO
Edit: Revisiting this answer after two months I realize that it is a little short (to say the least) on explanation: So this will actually "redirect" the request to the last selected admin page so that it will show up in the URL. I have updated the Plunkr and added a function to show the current document URL. So one can see that after clicking on /admin/ the URL will actually be /admin/12345 if this was the admin sub page visited before.