The parent route doesn't contain any view. I put the child routes in a parent to share its name so that the url becomes like this .../sites/site1 or .../sites/site2
$stateProvider
.state('sites', {
url: '/sites',
abstract: true
})
.state('sites.site1', {
url: '/site1',
templateUrl: 'templates/site1.html'
})
.state('sites.site2', {
url: '/site2',
templateUrl: 'templates/site2.html'
})
// ...
// Other routes
But this doesn't seem to work when I go to :
<a ui-sref="sites.site1">Go to first site</a>
<a ui-sref="sites.site2">Go to second site</a>
Nothing's showing up. (Other normal routes are working fine)
There must be a target in parent for a child:
.state('sites', {
url: '/sites',
abstract: true,
// THIS line is essential,
// 1) it will inject the parent template into root
// (index.html) ui-view=""
// 2) and will also create a target for a child view
template: '<div ui-view=""></div>',
})
The reason is: child state is using implicit view naming, expecting that parent will have some unnamed target ui-view=""
Related
I'm trying to use angular ui-router in my project and I'm running into an issue about maintaining url parameters in the parent route while adding child ones...
I have a settings page with the following route: /settings/:messageCode/:status
And now I need to add a piece of template that changes depending on the route so the new display looks like this: https://imgur.com/a/dHKzVD6
<div>
<div id="sidebar">...</div>
<div id="topbar">...</div>
<div ui-view>
<!-- This is the variable content depending on the route -->
</div>
</div>
The new routes I need to add are the following:
/settings/studio
/settings/payments
And this is my code for the nested routing
...
$stateProvider
.state("register", {...})
.state("settings", {
url: "/settings", // the objective is to keep the previous route "/status/:messageCode/:status"
templateUrl: 'settings/settings.view.html',
controller: 'SettingsCtrl as vm',
params: {
messageCode: {
value: null,
squash: true,
dynamic: true,
},
success: {
value: null,
squash: true,
},
})
.state("settings.studio", {
url: "/studio",
templateUrl: 'template-tab-studio.html',
controller: 'SettingsCtrl as vm',
})
.state("settings.payments", {
url: "/payments",
templateUrl: 'template-tab-payments.html',
controller: 'SettingsCtrl as vm',
})
At the moment, the routing is working fine, but I lost the URL params on the parent component (settings home), while adding its new children without having to add the url parameters to all childrens.
The problem of having to add the URL params to all children, is that I'll need to add many more views, so having to maintain all that routes will complicate things.
Is there a way to keep the original route in the parent (/settings/:messageCode/:status) while adding children so they can also recieve that paremeters?
Target routes would look like this: /settings/{dinamicView}/:messageCode/:status.
can't get what parameters do you mean, to pass variables to child route you could use resolve
to keep previous route change url: "/settings" to url: "settings"
I'm trying to create 2 separate URL states within the same config file.
I was following this template below.
$stateProvider.state('parent', {
data:{
customData1: "Hello",
customData2: "World!"
}
})
.state('parent.child', {
data:{
// customData1 inherited from 'parent'
// but we'll overwrite customData2
customData2: "UI-Router!"
}
});
My code is below. The /reports/moveFrom works fine; however, the /drillDown route is not even registering. Hitting that url sends me back to my apps homepage.
I'm wondering if the parent.child notation is getting messed up by the app.report_moveFrom.drillDown as it has 2x (.)
Any help would be greatly appreciated.
$stateProvider
.state('app.report_moveFrom', {
url: '/reports/moveFrom',
views:{
'main': {
template: require('./moveFrom.html'),
controller: 'moveFromController as $ctrl'
}
},
title: 'moveFrom'
})
.state('app.report_moveFrom.drillDown', {
url: '/drillDown',
views:{
'main': {
template: require('./drillDown.html'),
controller: 'moveFromController as $ctrl'
}
},
title: 'drillDown'
})
Can you please add the code that you using to make a call.
You should be calling something like this:
/reports/moveFrom/drillDown
If you are not doing this, kindly change it once and check
This is the piece from the lib:
$stateProvider
.state('contacts', {
abstract: true,
url: '/contacts',
// Note: abstract still needs a ui-view for its children to populate.
// You can simply add it inline here.
template: '<ui-view/>'
})
.state('contacts.list', {
// url will become '/contacts/list'
url: '/list'
//...more
})
.state('contacts.detail', {
// url will become '/contacts/detail'
url: '/detail',
//...more
})
The point is: each . (dot) in state name represents nesting. I.e
// child of the 'app' state
.state('app.report_moveFrom', {
// child of the above 'app.report_moveFrom'
.state('app.report_moveFrom.drillDown', {
Also, any view targeting, is using by default relative naming. It means, UI-Router searches for (un)named view in the parent state. So, the 'app.report_moveFrom' must contain app.report_moveFrom if we use this syntax as this:
// parent for next state
.state('app.report_moveFrom', {
...
// the default view name resolution is related to parent
.state('app.report_moveFrom.drillDown', {
url: '/drillDown',
views:{
// that ui-view="main" target must be in the above state
'main': {
...
and finally, if we have a child, it inherits the parent url as well
// parent url
.state('app.report_moveFrom', {
url: '/reports/moveFrom',
...
})
//child url - is later extended with parent part
.state('app.report_moveFrom.drillDown', {
url: '/drillDown',
...
// and in runtime this state has '/reports/moveFrom' + '/drillDown'
// i.e.: '/reports/moveFrom/drillDown'
But we can change this default behavior, with just a few tricks.
1) Reset url, to start at root, and 2) target grand parent, with absolute view naming
.state('app.report_moveFrom.drillDown', {
// this sign at the beginning will rest url evaluation - to root level
url: '^/drillDown',
views:{
// we use absolute naming here, so this state will be placed into grand parent 'app'
'main#app': {
...
But the best would be (in my view) simply remove the '.' from the state name, and by default create a sibling (not a child)
.state('app.report_moveFrom', {
// remove dot
//.state('app.report_moveFrom.drillDown', {
.state('app.report_moveFrom_drillDown', {
...and now all will be working by design - because we did not created too much nested state
Below is how the ui-router state provider has been set for our project. Showing below a part of it.
$stateProvider
.state('Parent', {
url: '/mainpath/:Id',
templateUrl: getViewUrl('Main.html'),
controller: 'MainController',
controllerAs: 'main',
abstract: true,
resolve: {
})
.state('Parent.Child', {
templateUrl: getViewUrl('Child.Html'),
controller: 'ChildController',
controllerAs: 'child',
url: '/child',
requireADLogin: true
})
.state('Parent.Child1', {
templateUrl: getViewUrl('Child1.Html'),
controller: 'Child1Controller',
controllerAs: 'child1',
url: '/child1',
requireADLogin: true
})
.....many more child state.
Parent Path Contains url as '/mainpath/:Id', the Id is part of the parent and based on this value parent runs a number of resolve before loading any of the child state(parent being abstract cannot be navigated to any which way).
The end URL looks like http://something/x.html/mainpath/124353534/child1, the final html contains top section which is parent and below section contains the child
<Html>
<Parent>
<Child>
</Child>
<Parent>
</Html>
On the Parent HTML there is a dropdown list to change the Id in the path '/mainpath/:Id'(this is the problem), this value in the dropdown is captured in the main controller (parent) and the current child state is reloaded with $state.go('passing the new ID cause child value will change based on this Id'). All works fine except that i am not able to change the Id value in the URL.
Can you guys please help with this.
I would store the id's in a service, and inject this service to the different controllers that uses it.
I have the following states declaration (angular v1.5.5):
$stateProvider
.state('appPublic', {
abstract: true,
data: { restricted : false }
})
.state('home', {
url: '/',
parent: 'appPublic',
templateUrl: 'app/views/main.html',
controller: 'mainCtrl'
});
When I open my site, I don't see the main html content (the home state). But, when I remove the parent: 'appPublic' declaration - it works then. So, why I can't to specify the state's parent ?
Every parent, must provide a view target for its child (if using unnamed views are used, i.e parent is not skipped with absolute view naming - Angularjs ui-router not reaching child controller). So this should work
.state('appPublic', {
abstract: true,
data: { restricted : false },
template: '<div ui-view=""></div'
})
now, child view (unnamed view) will be placed in the ui-view target, declared in parent's template
try this:
$routeProvider.when('/userLogin',
{
templateUrl: 'WebrtcLogin.html',
controller: 'UserLoginController'
})
ok, I needed to include template: '<ui-view/>' in my abstract state. The answer is here https://stackoverflow.com/a/33181762/106616
I have app with many main states, one of them is user profile:
$stateProvider.state('profile', {
url: '/profile/',
templateUrl: 'profile/profile.html',
controller: 'Profile',
});
But this is just an container for nested pages with different profile settings. It's template only contains main menu and ui-view for nested states. Controller is only for that menu handling.
One of nested views should be default url and have same URL as parent, so there shouldn't be any suffixes added into url, but I can't achieve that.
Here's what I tried:
$stateProvider.state('profile.details', {
url: '',
templateUrl: 'profile/details.html',
controller: 'ProfileDetails',
});
this is not working at all, at url /profile/ only menu appears and an empty ui-view element. Second approach:
$stateProvider.state('profile.details', {
url: '/',
templateUrl: 'profile/details.html',
controller: 'ProfileDetails',
});
This matches on url /profile// (with 2 slashes at end). At url /profile/ there is still menu and empty ui-view element.
How can I achieve that result? Is this even possible using angular-ui-router?
Make your parent state abstract. This will prevent from going into that state, and force to go to child states only. Abstract states are perfect as templates for child ones. Also get rid of url:
$stateProvider.state('profile', {
abstract: true,
templateUrl: 'profile/profile.html',
controller: 'Profile',
});
Now for your child state define absolute URL
$stateProvider.state('profile.details', {
url: '^profile',
templateUrl: 'profile/details.html',
controller: 'ProfileDetails',
});
That should work.