controllerA from state A
$state.go('account.accountRegister', {accountType: $stateParams.accountType, acName: acName})
State defined in app.js
.state('account.accountRegister', {
url: '/:accountType/register',
params: {accountType, acName},
views: {
'mainView#':{
templateUrl: 'app/views/registration.html',
controller: 'registrationController'
}
}
})
controllerB from state B
console.log($stateParams.acName); // is getting undefined
How to use acName in the controller without showing in the url part of the state?
I came up with a solution
.state('account.accountRegister', {
url: '/:accountType/register',
params: {
acName: {
value: 'defaultValue',
squash: false
}
},
views: {
'mainView#':{
templateUrl: 'app/views/registration.html',
controller: 'registrationController'
}
}
})
For more info on squash property of the params object:
https://ui-router.github.io/docs/0.3.1/#/api/ui.router.state.$stateProvider
Related
I am on angular 1.6. Trying to override value of a ui-router state.
Initial states as follows :
$stateProvider.state('parent', {
abstract: true,
parent: 'ancestor',
url: '/parent',
data: {
authorities: [A,B]
},
views: {
'content#': {
templateUrl: 'app/scripts/myapp/module/parent.html'
}
}
})
.state('child', {
parent: 'parent',
abstract: true,
views: {
'tabs': {
templateUrl: 'app/scripts/myapp/module/submodule/child.html',
controller: 'ChildController',
controllerAs: 'childController'
}
}
})
.state('grandChild', {
parent: 'child',
url: '/{dataSource:(?:option1|option2|option3)}',
views: {
'body': {
templateUrl: 'app/scripts/myapp/module/submodule/grandchild.html',
controller: 'GrandChildController',
controllerAs: 'grandChildController'
},
},
resolve: {
groups: ['MyService', '$transition$', function (MyService, $transition$) {
var selectedSource = $transition$.params().dataSource ? $transition$.params().dataSource : 'option1';
return MyService.getGroups(selectedSource);
}]
}
})
Then in one of sub-implementation I am trying to override value of url - adding option4 for one of the state.
var states = $stateRegistry.deregister('grandChild');
$stateRegistry.register(states[0]);//There is one more child. For simplicity not showing here.
states[1].url.pattern = '/{dataSource:(?:option1|option2|option3|option4)}';
$stateRegistry.register(states[1]);
when I do following on 'grandChild'
$state.go('grandChild', {dataSource: 'option4'});
I get error as
Param values not valid for state 'grandChild'. Invalid params: [ dataSource ]
when I inspect $state
I see something weird.
$state.$current.params.datasource.type.pattern = /(?:option1|option2|option3)/
$state.$current.url.pattern = "/{dataSource:(?:option1|option2|option3|option4)}"
$state.$current.url._compiled[0] = /((?:option1|option2|option3))/
I have my state configurations defined as below:
$stateProvider
.state('parentState', {
abstract: true,
url: '/:tenantId/',
param: {
tenantId: {
array: false
}
},
views: {
'header#': {
templateUrl: 'home/header.html',
controller: 'Header as vm'
},
'footer#': {
templateUrl: 'home/footer.html',
controller: 'FooterCtrl as vm'
}
},
resolve: userResolve,
data: {
private: true
}
})
//...4-5 other child states, then a state to handle unknown urls
.state('parentState.otherwise', {
views: {
'#': {
templateUrl: 'home/404/pageNotFound.html',
controller: 'PageNotFoundCtrl as vm'
}
}
});
$urlRouterProvider.otherwise(function ($injector) {
$injector.get('$state').go('parentState.otherwise', {}, {
location: false
});
});
Now, when an invalid URL is entered, parentState.otherwise state loads correctly, and parentState param, i.e. tenantId, is also correctly filled.
However, on page reload(refresh, Ctrl + R) with same invalid URL, parentState.otherwise state loads, but the problem is parentState param, i.e. tenantId is coming as empty string("").
Somehow, with location: false, the parent state, i.e. parentState in this case, was not picking up tenantId param from the URL on page refresh. So, if we explicitly pass tenantId param to child state, i.e. parentState.otherwise while opening it, everything works perfectly even on page refresh:
$urlRouterProvider.otherwise(function ($injector) {
$injector.get('$state').go('parentState.otherwise', {
tenantId: 'someTenantId'
}, {
location: false
});
});
I want to be able to pass some state params that will show up in the route, and some that won't.
It would be nice to be able to do this:
.state('widgetadmin.widgets.widget', {
url: '/widget/{widgetId}/{friendlyName}',
views: {
"sub#widgetadmin": {
controller: 'WidgetAdminController as vm',
templateUrl: 'widgetadmin/widgets/widget.tpl.html',
params: { widgetHref: null }
}
},
data:{ pageTitle: 'Edit Widget' }
}
Then pass it like this:
$state.go('widgetadmin.widgets.widget',
{widgetId: widget.id, friendlyName: slug, widgetHref: widget._links.self.href},
{reload: true});
But when I try to access it, it's undefined:
var something = $stateParams.widgetHref;
How can I pass some state params in route, and some not?
Needed to put the params in a different place:
.state('widgetadmin.widgets.widget', {
url: '/widget/{widgetId}/{friendlyName}',
views: {
"sub#widgetadmin": {
controller: 'WidgetAdminController as vm',
templateUrl: 'widgetadmin/widgets/widget.tpl.html'
}
},
data:{ pageTitle: 'Edit Widget' },
params: { widgetHref: null }
}
When using ui-router's $state.go() in my Ionic app, the onEnter method is not called.
The states would be transitioning from tab.settings to tab.queries. The state transitions fine. How do I get the onEnter method to be called from $state.go() call? Does onEnter not get called when entering child views?
Route
$stateProvider
.state('tab', {
url: "/tab",
abstract: true,
templateUrl: "templates/tabs.html"
})
.state('tab.queries', {
url: '/queries',
views: {
'tab-queries': {
templateUrl: 'templates/tab-queries.html',
controller: 'QueryCtrl',
onEnter: function() {
activate();
}
}
}
})
.state('tab.settings', {
url: '/settings',
views: {
'tab-settings': {
templateUrl: 'templates/tab-settings.html',
controller: 'SettingsCtrl'
}
}
});
SettingsCtrl
vm.removeAll = function() {
Data.removeAll().then(function() {
$state.go('tab.queries');
});
};
QueryCtrl
function activate() {
console.log('Activating');
}
Try moving the onEnter from within the view object up a level to the state object, I've just ran across this same problem and it seemed to work OK for me.
.state('tab.queries', {
url: '/queries',
views: {
'tab-queries': {
templateUrl: 'templates/tab-queries.html',
controller: 'QueryCtrl'
}
},
onEnter: function() {
activate();
}
})
My angular app is routed as following:
$stateProvider
// setup an abstract state for the tabs directive
.state('tab', {
url: "/tab",
abstract: true,
templateUrl: "templates/tabs.html"
})
// Each tab has its own nav history stack:
.state('tab.dotnet', {
url: '/dotnet',
views: {
'tab-dotnet': {
templateUrl: 'templates/tab-dotnet.html',
controller: 'QuestionsCtrl'
}
}
})
.state('tab.sql', {
url: '/sql',
views: {
'tab-sql': {
templateUrl: 'templates/tab-sql.html',
controller: 'QuestionsCtrl'
}
}
})
The above two routes use the same controller but different html pages.
Since both the pages are same, I want to have a single html page in my application instead of two different tab-sql and tab-dotnet pages.
But I will need a differentiation variable to be injected to the controller when selecting the tabs.
Basically I need something like this:
.state('tab.dotnet', {
url: '/dotnet',
views: {
'tab-dotnet': {
templateUrl: 'templates/tab.html',
controller: 'QuestionsCtrl',
type: 'dotnet' // so that i get this type in my Controller
}
}
})
.state('tab.sql', {
url: '/sql',
views: {
'tab-sql': {
templateUrl: 'templates/tab.html',
controller: 'QuestionsCtrl',
type: 'sql'
}
}
})
How to achieve this?
You can pass data to controllers in a state using resolve.
.state('tab.dotnet', {
url: '/dotnet',
views: {
'tab-dotnet': {
templateUrl: 'templates/tab.html',
controller: 'QuestionsCtrl',
resolve: {
type: 'dotnet';
}
}
}
})
.state('tab.sql', {
url: '/sql',
views: {
'tab-sql': {
templateUrl: 'templates/tab.html',
controller: 'QuestionsCtrl',
resolve: {
type: 'sql';
}
}
}
})
https://github.com/angular-ui/ui-router/wiki#resolve