Angular2 - Shared Layout for multiple modules

2019-02-20 03:18发布

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.

1条回答
男人必须洒脱
2楼-- · 2019-02-20 04:03

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.

查看更多
登录 后发表回答