Search code examples
angulartypescriptangular-routingangular-router

Angular routing: selective change of named outlets or don't reload submodule


I have the following routing configuration. It works as expected, but I don't want to reload Module2 ListComponent on every routing event. If the user clicks on a list item on ListComponent it shouldn't reload the list itself.

For example if I'm on module2/route1 and I navigate to module2/route2 I'd like only the details outlet to be updated and not the list.

My first thought was to change <router-outlet name="list"></router-outlet> to <app-list-component></app-list-component> but this way the list component is reloaded all the time, the same as it was handled by the router. I assume this is because the app-routing reloads the whole thing again. How can I avoid this?

app.component.html

  <router-outlet></router-outlet>

app-routing.module.ts

  const routes: Routes = [
  {
    path: 'module1',
    loadChildren: () =>
      import('./module1/module1.module').then(
        (m) => m.Module1Module
      ),
  },
  {
    path: 'module2',
    loadChildren: () =>
      import('./module2/module2.module').then(
        (m) => m.Module2Module
      ),
  },

module2.component.html

  <router-outlet name="list"></router-outlet>
  <router-outlet name="details"></router-outlet>

module2-routing.module.ts

const routes: Routes = [
  {
    path: `route1`,
    component: Module2Component,
    children:
    [
      {
        path: '',
        outlet: 'list',
        component: ListComponent,
      },
      {
        path: '',
        outlet: 'details',
        component: Main1Component
      }
    ],
  },
  {
    path: `route2`,
    component: Module2Component,
    children:
    [
      {
        path: '',
        outlet: 'list',
        component: ListComponent,
      },
      {
        path: '',
        outlet: 'details',
        component: Main2Component
      }
    ],
  },
  {
    path: '',
    component: Module2Component,
    children:
    [
      {
        path: '',
        outlet: 'list',
        component: ListComponent,
      }
    ],
  },

Solution

  • Please use this style of routing, where we have a empty string parent, which contains the list component, then we will re-render, the child routes which only refresh and list component does not refresh!

    Routing

    import { NgModule } from '@angular/core';
    import { RouterModule, Routes } from '@angular/router';
    import { Module2Component } from './module2/module2.component';
    import { Main2Component } from './main2/main2.component';
    import { Main1Component } from './main1/main1.component';
    
    const routes: Routes = [
      {
        path: ``,
        component: Module2Component,
        children: [
          {
            path: 'route1',
            component: Main1Component,
          },
          {
            path: 'route2',
            component: Main2Component,
          },
        ],
      },
    ];
    
    @NgModule({
      imports: [RouterModule.forChild(routes)],
      exports: [RouterModule],
    })
    export class Module2RoutingModule {}
    

    Module2 component

    <app-list />
    <router-outlet></router-outlet>
    

    Stackblitz Demo