My current configuration:
const routes: Routes = [
{ path: '', component: NavComponent, outlet: 'nav' }, // (1)
{ path: '**', component: NavComponent, outlet: 'nav' } // (2)
];
It works. NavComponent
is always rendered to the outlet nav
. In particular, it works for all the following kinds of URLs:
http://example.com/foo(nav:bar) // (a) non-empty path in nav --> (2)
http://example.com/foo(nav:) // (b) empty path in nav --> (2)
http://example.com/foo // (c) no nav at all --> (1)
Notice that the router matches different routes to these URLs:
(1)
is used for (c)
(2)
is used for (a)
and (b)
That is why the NavComponent
instance is destroyed and recreated every time the location changes say from (c)
to (a)
. And that's something I need to prevent. I need to keep my instance because of its state, animations, etc. As far as I understand, it's possible only if the same route is used for all the URLs, however I can't find a way to do this. If I remove (1)
, the URLs like (c)
stop showing NavComponent
in nav
. Apparently **
doesn't match such URLs (I'm not sure why though).
You can see it in action here: https://stackblitz.com/edit/angular-ptzwrm
What is the proper solution here?
For now, I'm overriding UrlSerializer
to add (nav:)
to URLs like (c)
before parsing, but it feels like a hack.
You can have multiple router-outlet in same template by configuring your router and providing name to your router-outlet, you can achieve this as follows. Advantage of below approach is thats you can avoid dirty looking URL with it. eg: /home(aux:login) etc.
Angular Router supports multiple outlets in the same application. A component has one associated primary route and can have auxiliary routes. Auxiliary routes enable developers to navigate multiple routes at the same time.
The path can take a wildcard string (**). The router will select this route if the requested URL doesn't match any paths for the defined routes. This can be used for displaying a “Not Found page” view or redirecting to a specific view if no match is found.
By Rob Gravelle. February 11, 2022. As the name suggests, the primary purpose of Angular Route Guards is to guard access to a certain route, such as an authenticated area of your app, or an admin section that requires special permissions to be accessed.
Dumb question, but can you not simply modify the URL using location service and stay on the same component (and just change states for your animations)?
Otherwise, you can implement a custom RouteReuseStrategy to force reusing your component
import { RouteReuseStrategy } from '@angular/router';
import {ActivatedRouteSnapshot} from '@angular/router';
import { DetachedRouteHandle } from '@angular/router';
/** Use defaults from angular internals, apart from shouldReuseRoute **/
export class CustomReuseStrategy implements RouteReuseStrategy {
shouldDetach(route: ActivatedRouteSnapshot): boolean { return false; }
store(route: ActivatedRouteSnapshot, detachedTree: DetachedRouteHandle): void {}
shouldAttach(route: ActivatedRouteSnapshot): boolean { return false; }
retrieve(route: ActivatedRouteSnapshot): DetachedRouteHandle|null { return null; }
shouldReuseRoute(future: ActivatedRouteSnapshot, curr: ActivatedRouteSnapshot): boolean {
let name = future.component && (<any>future.component).name;
return future.routeConfig === curr.routeConfig || name == "NavComponent";
}
}
@NgModule({
providers: [
{
provide: RouteReuseStrategy,
useClass: CustomReuseStrategy
}]
})
export class AppModule { }
Here is your modified stackblitz, which will always reuse your NavComponent
https://stackblitz.com/edit/angular-tj5nrm?file=app/app.module.ts
Links
Route reuse Strategy explained: https://medium.com/@gerasimov.pk/how-to-reuse-rendered-component-in-angular-2-3-with-routereusestrategy-64628e1ca3eb
Default values for angular router strategy: https://github.com/angular/angular/blob/master/packages/router/src/route_reuse_strategy.ts
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