I'd like to prevent a route from being accessed as long as a promise hasn't been resolved. Also, I'd like to pass the return value of that promise to the route component.
Several posts on SO recommend using the OnActivate
interface for this. The documentation says: "If routerOnActivate
returns a promise, the route change will wait until the promise settles to instantiate and activate child components." Sounds perfect, only the route still gets activated immediately... (Is it because it's the child components of Route2 that will wait for the promise, not the Route2 component itself??)
See https://plnkr.co/edit/ipKrOgfRj0vKk8ZejH5v?p=preview. The Route2 component implements the OnActivate
interface, but when you click the Route2 link, the Route2 component is activated immediately. However, the URL does update to /route2
only after the promise has resolved. (Launch the Plunker in a separate window to see what I mean.) Now I don't care so much about the URL, the Route2 component should not instantiate at all until the promise is resolved.
My other strategy was to use the @CanActivate
decorator. It better suits my purpose as "it is called by the router to determine if a component can be instantiated as part of a navigation".
The problem here is how to pass data from the promise in the @CanActivate
decorator to the component?
I have seen people write their data into a property of the next
parameter of the decorator, and retrieve it in the next
parameter of the routerOnActivate
method.
For instance in next.params
(here):
@CanActivate((next) => {
return messageService.getMessage()
.then((message) => {
next.params.message = message;
return true;
});
})
export class MyComponent implements OnActivate {
routerOnActivate(next) {
this.message = next.params.message;
}
}
Or in next.routeData.data
(here).
But the documentation says ComponentInstruction objects "should be treated as immutable". This is confusing.
Is this the best way to do this?
Maybe the router in its current state isn't finalized and there will be a better way when a stable Angular 2 is released?
Update
This is implemented in the new router
>= RC.4
Original
That's actually the case. There were lots of discussions recently about further progress and several changes are planned.
See also
- Angular Weekly Meeting (April 4)
- Router: Design for routerCanActivate, an injectable alternative to @CanActivate
AFAIK the params is supposed to be immutable and should not be modified.
The discussions in [router] CanActivate and DI show how to use DI with
CanActivate
. This is the approach I would use. Share a service globally and inject it inCanActivate
to update the values and inject it also in the components where you want to get access to the value.