Long post ahead. Egghead.io has some good tutorials on ui-router and named views that I found really helpful (although I think the named-views one is pro-only, although-although a pro subscription to
What I did was define sub-routes in $stateManager. So my index.html has header, app and footer named views.
Here's my main routing:
angular.module 'clientApp.app', ['ng', 'ui.router']
.config ($stateProvider, $urlRouterProvider) ->
$stateProvider.state 'app',
abstract: true
views:
footer:
templateUrl: 'app/app-footer.html'
header:
templateUrl: 'app/app-header.html'
$urlRouterProvider.otherwise '/start'
(note that abstract is true and the 'app' ui-view has nothing in it).
Then here's my communities routing:
$stateProvider.state 'app.communities',
url: '/communities'
views:
'app@':
templateUrl: 'components/app-templates/wide-right.html'
'le...@app.communities':
templateUrl: 'app/communities/communities-all-left.html'
'ri...@app.communities':
templateUrl: 'app/communities/communities-all-right.html'
I have a wide-right and a three-column app template, both are pretty simple html files with appropriately-named view (left and right, or left, middle and right) that contain the relevant responsive grid stuff to lay out prettily. Note that I did not have to set header@ or footer@, as this state app.communities is a substate of app, and therefore inherits the top-level app routing for views it doesn't override.
Below is a subroute for looking at a particular community. In this case I'm re-overriding the app@ template, albeit with the same template. That's because this *used* to have the three-column template, and I've not updated things yet to be more simple. But I'm routing specific new templates into the left and right views.
$stateProvider.state 'app.communities.detail',
url: '/:communityId'
views:
'app@':
templateUrl: 'components/app-templates/wide-right.html'
'le...@app.communities.detail':
templateUrl: 'app/communities/communities-single-left.html'
'ri...@app.communities.detail':
templateUrl: 'app/communities/communities-single-right.html'
In this one, I'm overriding the right side view, but not the left side view (note the name there, ri...@app.communities.detal, that's where it was originally defined, you can easily make route-and-view naming mistakes here, or at least I've made plenty).
$stateProvider.state 'app.communities.detail.conversations',
url: '/conversations'
views:
'ri...@app.communities.detail':
templateUrl: 'app/communities/communities-detail.html'
more of the same:
$stateProvider.state 'app.communities.detail.conversations.detail',
url: '/:docId'
views:
'ri...@app.communities.detail':
templateUrl: 'app/communities/communities-detail-conversation.html'
So, my app's /communities/2/conversations/4 route displays conversation number 4 in the communities-detail-conversation template on the right side, information about community 2 in the left side of the screen, derived from the left@ communities-single-detail defined in app.communities.detail, and the same header and footer template defined way up at app.
Note that I deleted some other stuff from these layouts, notably the controller definitions.
The nice thing is that all my "pages" (communities, people, etc) can be defined as separate modules, instead of cluttering up a single /views folder somehwere. They add their routing info to the state manager at instantiation time. I can duplicate or not duplicate as necessary.
So I *also* have a login page thusly:
$stateProvider.state 'login',
url: '/login'
views:
header:
templateUrl: 'app/login/login-header.html'
footer:
templateUrl: 'app/login/login-footer.html'
app:
templateUrl: 'app/login/login.html'
which overrides all the named views. None of these templates have any reliance on logged-in-user data. One could also have a signup route as well.