I'm trying to take advantage of a custom RouteReuseStrategy and for that I'd like to suspend any subscriptions when a component is detached and other things like scrolling to the proper position.
I've checked for possible hooks, but apparently no additional lifecycle hooks have been added and OnDestroy isn't called.
I tried to add my own onDetach and onAttach hooks, but neither the ActivatedRouteSnapshots nor the DetachedRouteHandle will give me the instance of the current component (just the prototype?).
The only way I could get a grip on the component instance when navigating away by using the CanDeactivate guard, but that doesn't seem right. And I still couldn't find a way to add a hook for onAttach.
So my question is, how can I properly suspend a component when detached and resume it when attached ?
There used to be a OnActivate
hook-interface in @angular/router
, but that seems to be gone and I didn't see any replacement.
P.S. there seem to some reports of Angular apps with custom RouteReuseStrategies slowing down when used for extended time, probably because there is no way to pause/resume components.
Lifecycle hooks link A component instance has a lifecycle that starts when Angular instantiates the component class and renders the component view along with its child views. The lifecycle continues with change detection, as Angular checks to see when data-bound properties change, and updates both the view and the component instance as needed.
There are a few who only execute once after component initialization. All lifecycle methods are available from @angular/core. Although not required, Angular recommends implementing every hook. This practice leads to better error messages regarding the component.
Respond to events in the lifecycle of a component or directive by implementing one or more of the lifecycle hook interfaces in the Angular core library. The hooks give you the opportunity to act on a component or directive instance at the appropriate moment, as Angular creates, updates, or destroys that instance.
After your application instantiates a component or directive by calling its constructor, Angular calls the hook methods that you have invoked at the appropriate point in that instance's lifecycle. Angular executes hook methods in the following order. You can use it to perform the following types of tasks.
I fixed it (yes this is more a bug than a missing feature).
Extend RouterOutlet and override attach()
and detach()
(see below), then replace your <router-outlet>
tags with <app-router-outlet>
.
If your component has a onDetach
and/or onAttach(ref: ComponentRef<any>, activatedRoute: ActivatedRoute)
method, it will be called.
import {ComponentRef, Directive} from '@angular/core';
import {ActivatedRoute, RouterOutlet} from '@angular/router';
@Directive({
selector: 'app-router-outlet',
})
export class AppRouterOutletDirective extends RouterOutlet {
detach(): ComponentRef<any> {
const instance: any = this.component;
if (instance && typeof instance.onDetach === 'function') {
instance.onDetach();
}
return super.detach();
}
attach(ref: ComponentRef<any>, activatedRoute: ActivatedRoute): void {
super.attach(ref, activatedRoute);
if (ref.instance && typeof ref.instance.onAttach === 'function') {
ref.instance.onAttach(ref, activatedRoute);
}
}
}
P.S. Even with that fix custom RouteReuseStrategies are still pretty useless, without access to history states
or preserved data
in the ActivatedRoute
there is no way of identifying two instances with the same routeConfig/path.
Paired with some weird timing of angular's calls to RouteReuseStrategy, Router Navigation Events and history.pushState it's extremely hard to write workarounds for that.
This is extremely frustrating to work with.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With