Feature request: ability to defer route changes pending asynchronous action
Hello,
I watched the last Polycast about lazy loading. In the Polycast, Rob lazy load the elements before changing the route using page.js. It would be great to be able to run some logic before changing the page using carbon-route.
In the normal flow of things, a carbon-route consumes a route and produces a tail. perhaps consuming a new route can stand-in as an opportune moment to let an observer of the route defer production of the tail. For (extremely hypothetical) example:
<template>
<carbon-route route="{{route}}" on-navigate="onNavigate" tail="{{tail}}"></carbon-route>
</template>
<script>
Polymer({
is: 'x-defers-route-change',
onNavigate: function(navigateEvent) {
// `tail` will not be produced until `somePromise` resolves:
navigateEvent.defer(somePromise);
}
});
</script>
@rictic WDYT?
I'm not sure if that would be enough for this use case. I think that you want to configure the loading promise on the route that's being navigated to, rather than the current route that's being navigated from.
At a broader level, one concern I have with delaying transitions is that it can give a great user experience during development when latencies are low but result in an unresponsive UI in production. I think that the pattern that we want to encourage here is one where you transition immediately and display a loading indicator while any necessary code & data loads. I've got a WIP version of zuperkulblog that does this.
It's possible that there are use cases I haven't considered. Interested in hearing feedback on this.
As a coincidence, I was fiddling with this concept and came up with iron-lazy-pages. Would such an element suit your use-case?
Personally, I think it is better to put such logic in selector elements that receive the route to let the developer decide which mechanism to use. This to prevent a carbon-route that "does-all-the-things".
An element like iron-lazy-pages can suit my use-case, but what if i want to use neon-anmated-pages to have animation when switching between pages? I agree with you, maybe the lazy loading should be managed in iron-pages or neon-animated-pages instead of the router.
You can use these as a lazy loading replacement for neon-animated-pages: https://github.com/atotic/lazy-pages
I think that you want to configure the loading promise on the route that's being navigated to
This is what I intended to illustrate in my example. The navigate event fires when the new route is consumed, allowing the user to defer production of the tail. Sorry if it was ambiguous.
At a broader level, one concern I have with delaying transitions is that it can give a great user experience during development when latencies are low but result in an unresponsive UI in production.
Sure, but shouldn't we make it as easy as possible for the user to decide when and how transitions are deferred?
I think that the pattern that we want to encourage here is one where you transition immediately and display a loading indicator while any necessary code & data loads.
It seems like an open-ended enough problem that we may not want to enforce any particular pattern. Loading indicators are not always the most ergonomic UI for the job. In some cases, your latency will be consistently low and deferral is nice because it spares the user from FOUC - a loading indicator wouldn't help you here.
Regarding lazy pages: it's great to build elements that have ergonomic transitions baked in. But, it's also good for an element like carbon-route to supply the means to create such transitions with arbitrary components without the need for coordination.
I see your point about it being disruptive to the display for consistently low latency operations.
I'm not entirely sure I understand how this would work if the configuration is only on the receiving carbon-route (i.e. the one that becomes active after the navigation).
Imagine a simple UI that's structured like this:
<app>
<user-page>
<profile-page>
<user-details-page>
<store-page>
<item-detail-page>
In order to support delayed navigation when someone navigates from <item-detail-page> to <profile-page> then wouldn't <store-page> and <app> have to know that <item-detail-page> may delay navigation, and not transition to displaying <user-page> until it's ready?
Because if we're only delaying the production of the tail property then it seems like the navigation would proceed instantly until it hits the <user-page>, at which point the previous view is no longer displayed.
Depending on the implementation, I can imagine...
<app>may need to know (and per my straw man, it would)<store-page>may need to know that it will no longer be active, and may want to defer based on that information. I don't have a ready example for how the "outgoing" case might be dealt with.<user-page>would know, and have an opportunity to defer<profile-page>would know, and would have an opportunity to defer
However, I am not asserting that an outgoing page needs to know that an incoming page may defer navigation. To the contrary, routes should not have to have such special knowledge of each other.
My point is: an advantage of separating the consumption of route and the production of tail is that a single <carbon-route> has an opportunity to defer the progression of UI changes beyond its threshold of authority. This seems like a natural implementation nook where asynchronous behavior can be dealt with.