3

I build an Angular application with different modules. Each module handles distinct tasks. On my landing page, the user should login or register. It's a very lean layout without any navigation. On my feature modules (which are accessible after a login) the user can perform tasks and search for information.

My main problem is, that my feature modules should share the same layout (with navigation, toolbar and so on) while my AuthModule should not have the same layout. The following image should illustrate what I try to achieve.

enter image description here

Every module (Auth and Features) have their own RoutingModule and distinct set of components. The access to the Layout2 and the FeatureModules is protected by AuthService/AuthGuards.

I already found good solutions for a Component-based setup (https://stackoverflow.com/a/40508804/1365061 and https://stackblitz.com/edit/angular-multi-layout-example?file=app%2Fapp.routing.ts) but not for a module based one. I want to lazy load the feature modules and this can't be applied to the given solutions I found (at least it does not work for modules).

What can I do to share the layouts between the modules or in other words "load the modules within the layout component"?

My current code snippets are:

app.component

<router-outlet></router-outlet>

user-area.component

<mat-toolbar color="primary" class="mat-elevation-z2" *ngIf="(auth.account$ | async) as account">
    <button mat-button class="pull-left" [disabled]="!account" (click)="sidenav.toggle()">
        <i class="fa fa-navicon" aria-hidden="true"></i> SiteName
    </button>

    <button mat-button class="pull-left ml-3 pull-left" routerLink="/settings/profile">
        <img [src]="account.userID | avatar" class="rounded-circle mr-1" width="30" height="30">
        <span class="d-none d-sm-inline"> {{account.name}}</span>
    </button>

    <button id="logoutButton" mat-button class="pull-right" routerLink="/auth/logout">
        <i class="fa fa-power-off" aria-hidden="true"></i><span class="d-none d-sm-inline"> Logout</span>
    </button>
</mat-toolbar>

<mat-sidenav-container (window:resize)="onResize($event)" [style]="mainStyle.getValue()">
    <mat-sidenav *ngIf="auth.account$ | async" [mode]="sidenavMode" [opened]="true" #sidenav class="sidenav-shadow">
        <app-nav-pane *ngFor="let nav of (app.navmods$ | async)" [content]="nav"></app-nav-pane>
    </mat-sidenav>
    <div class="container-fluid">
        <div class="row" style="flex: 1 0 auto;">
            <div class="col-12">

                <router-outlet></router-outlet>
            </div>
        </div>
    </div>
    <app-footer *ngIf="responsiveService.mdOrLarger"></app-footer>
</mat-sidenav-container>

public.component

<div class="..." style="...">
   <router-outlet></router-outlet>
</div>

My app.routing.module routing:

const routes: Routes = [
    {
        path: 'auth',
        component: PublicAuthComponent,
        canActivate: [NotLoggedInGuard]
    },
    {
        path: '',
        component: UserAreaComponent,
        canActivate: [LoggedInGuard]
    }
];

As said I tried to use the concept from the above-mentioned links but it's not working as intended.

Alex
  • 1,857
  • 3
  • 36
  • 51
  • you can reference this link: https://stackoverflow.com/questions/40958304/router-link-not-working-for-a-component-inside-a-shared-module – Trunghieu Le May 18 '20 at 04:11

1 Answers1

5

You can use parent/children routing to achieve this. Something like this should work (may need some tweaking depends on the other parts of your project)

const routes: Routes = [
    {
        path: 'auth',
        component: Layout1
        canActivate: [NotLoggedInGuard],
        children: [
           { path: '', component: PublicAuthComponent }
        ]
    },
    {
        path: '',
        component: Layout2,
        canActivate: [LoggedInGuard],
        children: [
          { path: '', loadChildren: './path/to/module/feature.module#FeatureModule' }
        ]
    }
];

Remember to put <router-outlet> inside both of Layout components.

Mateusz Witkowski
  • 1,646
  • 10
  • 24
  • As said before I'm using Module Routing within every Module (distinct routing modules for each module). So, as far as I understand I can't use this routing concept. – Alex Mar 01 '18 at 13:08
  • I've updated my proposal so now path is pointing to feature module which is using its own routing. – Mateusz Witkowski Mar 01 '18 at 15:33
  • Should this be the path to the module itself or the routing module? I have multiple FeatureModules, would it be useful to create a "FeatureModuleRoutingModule" which handles all "not auth routings"? – Alex Mar 01 '18 at 17:42
  • It's the path to the (lazy-loaded) module itself. I would go with separate routing module for every feature module. From my experience it's easier to maintain and refactor. But I don't know how does your application look as a whole so you need to make that decision on your own. – Mateusz Witkowski Mar 01 '18 at 18:10
  • Ok, this is working. My error was that I did not use the "loadChildren" routing parameter. Thanks. – Alex Mar 01 '18 at 20:46
  • This means feature module will be lazy loaded. If you don't want lazy loading I am afraid there is no way. – jbojcic Sep 29 '18 at 13:06