app-route
app-route copied to clipboard
Simplify mapping to `iron-pages` if the location scheme doesn't match the code structure
The mapping is very elegant if the URL scheme matches the code structure. For example (from https://www.polymer-project.org/1.0/articles/routing.html#example):
<carbon-route route="{{route}}" pattern="/tabs/:tabName" data="{{data}}">
</carbon-route>
<neon-animated-pages selected='{{data.tabName}}' attr-for-selected='key'>
<neon-animatable key='foo'>Foo Page Here</neon-animatable>
<neon-animatable key='bar'>Bar Page Goes Here</neon-animatable>
<neon-animatable key='baz'>Baz Page, the Best One of the Three</neon-animatable>
</neon-animated-pages>
Problem
It's getting considerable more complex if the key can't be directly extracted from the location (e.g. because an existing URL schema needs to be preserved).
For example, given these locations:
- #groups -> All groups
- #groups/:groupId -> Group profile page
- #groups/:groupId/member -> All members in a group
Mapping would require something along these lines:
<carbon-route route="[[route]]" pattern="/groups" active="{{isAll}}"></carbon-route>
<carbon-route route="[[route]]" pattern="/groups/:groupId" active="{{isProfile}}"></carbon-route>
<carbon-route route="[[route]]" pattern="/groups/:groupId/members" active="{{isMembers}}"></carbon-route>
<iron-pages attr-for-selected="key" selected="getKey(isAll, isProfile, isMember)">
<div key="all">...</div>
<div key="profile">...</div>
<div key="members">...</div>
</iron-pages>
...
/** Map the various flags for the `selected` property of iron-pages: */
getKey: function(isAll, isProfile, isMembers) {
// Workaround for issue #61: match most specific first
if (isMembers) return 'members';
if (isProfile) return 'profile';
if (isAll) return 'all';
return 'default';
}
Proposal
As a user, I'd love to get the key directly from the routing elements. For example, something along these lines:
<carbon-selected-route key="{{key}}">
<carbon-route route="[[route]]" pattern="/groups/:groupId/members" key="members"></carbon-route>
<carbon-route route="[[route]]" pattern="/groups/:groupId" key="profile"></carbon-route>
<carbon-route route="[[route]]" pattern="/groups" key="all"></carbon-route>
</carbon-selected-route>
The surrounding element would then return the key of the route that matching first.
The way I solve these sort of problems is by moving the inner-carbon-routes to the respective page element. In other words: the main neon-animated-pages is not aware of the inner-structure of the groupId and members sub-routes. Therefore the first selection only has groups. The tail is then passed along to the element, which itself has a carbon-route matching on the groupId and members respectively.
What I prefer of this solution is that my index.html is rather clean and is not required to know about all of my possible paths in my application. Also if I want to change an inner-route, only the corresponding page element needs to know the changes. Therefore my elements are more loosely coupled (and also even sharable).
@TimvdLippe Thanks for sharing your thoughts. The part I don't understand is how you avoid animations mixups. If the main neon-animated-pages is not aware of the inner-structure, how do you handle these two cases:
- Navigate within sub page,e.g. go from #groups/:groupId to #groups/:groupId/member
- Navigate to sub-page: go from #groups/:groupId to #xxx, and then from #xxx to #groups/:groupId/member
How do you ensure that exactly one animation is played in both cases?
What I prefer of this solution is that my index.html is rather clean and is not required to know about all of my possible paths in my application. Also if I want to change an inner-route, only the corresponding page element needs to know the changes. Therefore my elements are more loosely coupled (and also even sharable).
I can perfectly see this for greenfield projects where you can align the URL structure to the code structure. My use case refers more to situations where this isn't the case, e.g. when keeping the URL structure of the legacy application is a must (e.g. for migration, bookmarks, A|B tests, existing 3rd party applications that hardcode the structure, etc). In those situations, I explicitly don't want the legacy URL structure leak into my code structure.
I'm also suffering from the same issue, would like your feedback on how to overcome such an issues, I have decided to use the solution @ronnyroeller has suggested.