AngularJS child of child template not showing - angularjs

No errors.
I'm able to access a list of teams at /teams and a specific team at /teams/2 where 2 is the id of a team.
$stateProvider.state('app.teams.team', {
url: '/:team',
templateUrl: 'templates/teams/team.html',
controller: 'TeamCtrl',
resolve: {
team: function($stateParams, TeamsService) {
return TeamsService.getTeam($stateParams.team)
}
}
})
I'm not able to access the roster at /teams/2/roster.
$stateProvider.state('app.teams.team.roster', {
url: '/roster',
templateUrl: 'templates/teams/roster.html'
})
The page loads without errors, and shows templates/teams/team.html instead of templates/teams/roster.html

The problem is the way you treat your states inheritance.
With the current configuration:
app.teams.team state expect the url http://app.teams url/:team
and
app.teams.team.roster state expect the url http://app.teams.team url/roster
each child expect the parent state to hold a ui-view directive so the templateUrl can get injected to.
This mean that for the roster state you have the app.teams htmls, contains the team html, contains the roster html.
To load a diffrent html under same level stay in same hirerchial level ->
app.teams.team
app.teams.roster

I ended up making roster its own state, which works as intended.
$stateProvider.state('app.roster', {
abstract: true,
url: '/teams/:team/',
views: {
content: {
template: '<ion-nav-view></ion-nav-view>'
}
},
resolve: {
team: function($stateParams, TeamsService) {
return TeamsService.getTeam($stateParams.team)
}
}
})
$stateProvider.state('app.roster.index', {
url: 'roster',
templateUrl: 'templates/roster/index.html',
controller: 'TeamCtrl',
})

Related

What's wrong with my Ionic/Angular state inheritance?

I'm new to Ionic and AngularJS so I'm struggling with (hopefully) something simple. I have these two states:
.state('menu', {
url: '/mobile/beer',
controller: 'beerCtrl',
templateUrl: 'templates/beer-menu.html'
})
.state('detail', {
url: '/mobile/beer/:id',
controller: 'beerDetailCtrl',
templateUrl: 'templates/beer.html',
resolve: {
beer: function($stateParams, beerService) {
return beerService.findBeerById($stateParams.id)
}
}
})
The 'menu' state fetches all beers from a server and hand the list over to 'beer-menu.html' that contains an ion-list to display the list. When the user selects a beer in the list, the 'detail' states steps in to display more details about the beer.
It's all working but I want to improve it a bit by using an abstract state:
.state('beer', {
abstract: true,
url: '/mobile/beer'
})
.state('beer.menu', {
url: '',
controller: 'beerCtrl',
templateUrl: 'templates/beer-menu.html'
})
.state('beer.detail', {
url: '/:id',
controller: 'beerDetailCtrl',
templateUrl: 'templates/beer.html',
resolve: {
beer: function($stateParams, beerService) {
return beerService.findBeerById($stateParams.id)
}
}
})
It looks totally OK to me - esp because this is based on one of the 'Formulas' from the Ionic Framework website. Nevertheless the app stops working when I structure the states like that. I've tried to tweak it in various way but couldn't get it working. Do you see what's wrong?
As the UI-Router documentation you have to define also a template for abstract state 'beer':
Remember: Abstract states still need their own <ui-view/> for their children to plug into. So if you are using an abstract state just to prepend a url, set resolves/data, or run an onEnter/Exit function, then you'll additionally need to set template: "<ui-view/>".
See:
https://github.com/angular-ui/ui-router/wiki/Nested-States-and-Nested-Views#abstract-states

What's the purpose of adding the extra 'views:{'foo':{}}' when declaring a view in angular?

What's the purpose of declaring the a view with views:{} e.g.
.state('app.example', {
url: "/example",
views: {
'my-example': {
templateUrl: "views/example.html",
controller: 'myCtrl'
}
}
})
as opposed to this
.state('app.example', {
url: "/example"
templateUrl: "views/example.html",
controller: 'myCtrl'
}
})
It is used for having multiple parallel views for a single state. Example:
.state('app.example', {
url: "/example",
views: {
"example1": {
template: 'app.example.view1'
},
"example2": {
template: 'app.example.view2'
}
}
})
index.html
<ui-view = "view1">
</ui-view>
<ui-view = "view2">
</ui-view>
So effectively, your state has two parallel views. You can find the detailed explanation here.
It is used to show multiple views on a single page(state).We use the above method when we show multiple parallel views on a single page.Suppose you have a page in which you have to show different charts on different positions,we created multiple views and appended the chart on those positions.Hope this helps
Ok I figured it out and I created a codepen for this to get it to fit nicely inside other ionic app. This updates the child view when a button or a sidemenu item is pressed with more detail inside the codepen by making multiple child views share a name like so
views: {
'shared-child-view' :{
templateUrl: "[path to your children, in our case child1.html and child2.html]"
}
}`
where it would look something like this
.state('sidemenu.parent.child1', {
url: "/child1",
views: {
'shared-child-view' :{
templateUrl: "child1.html"
}
}
})
.state('sidemenu.parent.child2', {
url: "/child2",
views: {
'shared-child-view': {
templateUrl: "child2.html"
}
}
})
`
Where it can sit in a parent that sits in an abstract state like this (but it doesnt have to but It's likely that this is how your ionic app will be setup):
.state('sidemenu', {
url: "/sidemenu",
abstract: true,
templateUrl: "sidemenu.html"
})
.state('sidemenu.parent', {
url: "/parent",
views: {
'menuContent' :{
templateUrl: "parent.html"
}
}
})
You can alternate or change each child view inside a view to evrey view with the same name, in this case "shared-child-state"
<div ui-view name="shared-child-view"></div>
and it can be made clickable with
<a href="#/sidemenu/parent/child2" class="item">Child View 2
</a>
This doesnt work if you use ui-serf.
I hope this helps someone!

In ui-router, is it possible to have nested views within nested views?

I am doing my routing with ui-router and have a nested view that loads up some menu options for the item that is selected. My question is, is it possible to have nested views within a nested view with ui-router?
The code here works:
.state('settings', {
url: '/settings',
views: {
'': {
templateUrl: './templates/settings.html',
controller: 'settingsCtrl'
},
'details#settings': {
templateUrl: './templates/details.html',
controller: 'detailCtrl'
}
}
})
But say I wanted to load something attached to the details#settings view. How would I go about that? I have tried
.state('settings', {
url: '/settings',
views: {
'': {
templateUrl: './templates/main/settings.html',
controller: 'settingsCtrl'
},
'detail#settings': {
url: '',
views: {
'': {
templateUrl: './templates/detail.html',
controller: 'detailCtrl'
},
'contact#detail#settings': {
templateUrl: './templates/contactpref.html'
}
}
}
}
})
I don't get any errors in the console on this, but it does break my original nested view. From what I have found the docs aren't really clear on if this is even possible.
It is not possible. Check the: http://angular-ui.github.io/ui-router/site/#/api/ui.router.state.$stateProvider
and section views:
an optional map<string, object> which defined multiple views, or targets views manually/explicitly.
Examples:
Targets three named ui-views in the parent state's template
views: {
header: {
controller: "headerCtrl",
templateUrl: "header.html"
}, body: {
controller: "bodyCtrl",
templateUrl: "body.html"
}, footer: {
controller: "footCtrl",
templateUrl: "footer.html"
}
}
That is it. That's what UI-Router will see and resolve for us. And why are not you provided with any error?
Because expect value of the map<string, object> is object. It is iterated for known properties (controller, templateUrl) - and any uknown is ignored, not used, not found... skipped
Solution:
After some experience with UI-Router I would suggest:
if there are some features related - place them in state
if there are some more features related, but only with some conditions - place them into child state.
That structure will bring many benefits, mostly: stable parent (not reloading always) and dynamic child - placing new and new content into some targets/anchors/ui-views whenever parameter is changed. Check:
Trying to have one subview call another subview using ui-router

Angular UI Router - Reload reverts a transitioned state back to the parent state

I have an application which is role based, so I am using parent states to create layouts which are used across different roles, and then I have child states which add specific templates for the role which is necessary.
When the user authenticates the application, I am transitioning to the relevant role based state, but when you reload the page, the state is lost and it returns to the parent state.
Example Code
$stateProvider
.state('dashboard', {
url: '/dashboard',
views: {
'header#': {
templateUrl: 'partials/layout/sections/auth/header.html'
},
'content#': {
templateUrl: 'partials/dashboard/template.html'
},
'left-column#dashboard': {
templateUrl : 'partials/dashboard/left-column.html',
controller : 'DashNavCtrl'
}
},
data: {
layoutType: 'three-column'
}
})
.state('dashboard.admin', {
views: {
'centre-column#dashboard': {
templateUrl: 'partials/dashboard/recruiter/dashboard.html'
},
'right-column#dashboard': {
templateUrl : 'partials/dashboard/recruiter/right-column.html',
controller : 'DashSidebarCtrl'
}
},
data: {
authorisedRoles: [USER_ROLES.admin]
}
})
When I transition the user to the dashboard.admin state, on reload the user gets directed back to the empty containing state.
Is it possible to stop this from happening?

3 controllers on the same page showing different results for $state.is()

First of all, apologies I don't have an example to show. The current situation is I am using UI Router and I have 3 views with a different controller each on the same page with the state name 'result'. i.e. for the head, content and sidebar.
However, only 1 of the controllers (content) return true when I call for $state.is('result'). I've also tried $state.includes('result').
When I log the $state only, all 3's state object shows the same correct \result in $state.current.name, however, if I try to log $state.current directly, the name becomes blank for 2 of them.
I've tried swapping the order of the views, but only content is returning true.
I read the doc many times, but I can't find the reason why. Please help!
.state('result', {
url: '/result',
views: {
'headView' : {
templateUrl: 'modules/core/templates/head.html'
},
'contentView' : {
templateUrl: 'modules/core/templates/content.html'
},
'sidebarView' : {
templateUrl: 'modules/core/templates/sidebar.html'
},
}
})
Place your controllers in your state view definitions where your templateUrls are defined.
E.G.
DEMO
.state('result', {
url: '/result',
views: {
'headView' : {
templateUrl: 'modules/core/templates/head.html',
controller: 'HeadViewController',
},
'contentView' : {
templateUrl: 'modules/core/templates/content.html',
controller: 'ContentViewController'
},
'sidebarView' : {
templateUrl: 'modules/core/templates/sidebar.html',
controller: 'SidebarViewController'
},
}
})

Resources