I'm testing UI-Router
nested state, but I'm not able to set default state in parent/child scenario, please help.
libraries:
navigation path:
/ - home
/settings - parent state/page
/settings.default - child 1
/settings.mail - child 2
/settings.phone - child 3
expected behavior:
when navigating to /settings
, the default child 'general' state/page should be triggered/loaded
actual behavior:
If I set 'settings' state 'abstrat: true', there will be error:
Error: Cannot transition to abstract state 'settings'
at Object.transitionTo (angular-ui-router.js:3143)
at Object.go (angular-ui-router.js:3068)
at angular-ui-router.js:4181
at angular.js:16299
at completeOutstandingRequest (angular.js:4924)
at angular.js:5312
If I remove 'abstrat: true', there's no error, but when i navigate to /settings, default child state/page - general state not triggered, settings.html displayed but not loaded
app.js:
angular.module('test',['ui.router','sails.io']) //config routing
.config(['$stateProvider','$urlRouterProvider','$locationProvider',
function($stateProvider,$urlRouterProvider,$locationProvider) {
$urlRouterProvider.otherwise('/');
$locationProvider.html5Mode(true);
$stateProvider
.state('home', {
url: '/',
templateUrl: 'views/index.html',
controller: 'IndexController'
})
.state('settings', {
abstract: true,
url: '/settings',
templateUrl: 'views/settings.html',
controller: 'SettingsController'
})
.state('settings.general', {
url: '',
templateUrl: 'views/settings/general.html',
controller: 'SettingsController'
})
.state('settings.mail', {
url: '/mail',
templateUrl: 'views/settings/mail.html',
controller: 'SettingsController'
})
.state('settings.phone', {
url: '/phone',
templateUrl: 'views/settings/phone.html',
controller: 'SettingsController'
});
}]);
views/settings.html
<div class="container">
<div class="row">
<div class="col-md-3">
<ul class="list-group">
<li class="list-group-item"><a ui-sref=".general">General</a></li>
<li class="list-group-item"><a ui-sref=".phone">Phone</a></li>
<li class="list-group-item"><a ui-sref=".mail">Mail</a></li>
</ul>
</div>
<div class="col-md-9">
<div ui-view></div>
</div>
</div>
</div>
There is a working plunker
This would work, but just with url
navigation, i.e. href
:
<a href="/settings"> // will work
But this will not - we cannot go to abstract
state:
<a ui-sref="settings">settings</a>
But based on this Q & A:
We can remove abstract and create default state handling like this. There is updated plunker
// redirection engine
app.run(['$rootScope', '$state', function($rootScope, $state) {
$rootScope.$on('$stateChangeStart', function(evt, to, params) {
if (to.redirectTo) {
evt.preventDefault();
$state.go(to.redirectTo, params)
}
});
}]);
The parent stat adjustment:
.state('settings', {
//abstract: true,
redirectTo: 'settings.general',
url: '/settings',
...
Check it here
I realize this is an older question, but I thought I'd add something in case it helps someone else:
Although you may not want to add a plugin to solve this problem, you should check out UI-Router-Extras
There is a feature included there called "Deept State Redirect". This allows any state to save the most recently activated substate so that when you transition away, then back, the same substate (child state) will be active.
The part that would help your problem is being able to define a default child state. You do that by adding the "dsr" parameter and setting the "default" to whatever your child state is.
function myRouterConfig ($stateProvider, $urlRouterProvider) {
$stateProvider
.state('parentState', {
//Not in this file
parent: 'index',
sticky: true,
//ui-router-extras deepStateRedirect option
dsr: {
default: 'parentState.defaultChild'
},
url: '/parentState',
views: {
'main@index': {
template: '<my-parentStateComponent>'
}
}
})
.state('parentState.defaultChild', {
url: '/defaultChild',
views: {
'child@parentState': {
template: '<my-defaultChildComponent>'
}
}
});
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With