Multiple layouts for different pages in Angular 2

I have a login page - just 2 input (no header, no footer, no sidebar)

When a user signs in he should be navigated to a page with header, footer and right navbar.

the only thing that changes on the inner page is the right side content.

import { Component } from '@angular/core';
import { ViewEncapsulation } from '@angular/core';

@Component({
  selector: 'pm-app',
  template: `
  <div>
      <router-outlet></router-outlet>
   </div>
   `,
   styleUrls:["app/app.component.css"],
    encapsulation: ViewEncapsulation.None
})
export class AppComponent {
  pageTitle: string = 'Acme Product Management';
}

I understand this app.component is like master page where you can add the header and footer and the <router-outlet></router-outlet> is where the content changes based on the routing.

How do I make one layout for the login page and another layout with header, footer and right sidebar for the inside page?


You could use child routes to use different layouts for different views.

Here is a common example of using child routes in Angular2

I like to use child routes to separate secure pages and unsecure pages in my angular 2 applications.

In my app root I have two directories

/Public

&

 /Secure

Now in the root directory I also have

/app.routing.ts

from there I create a layouts folder,

/layouts

In that directory I create

/layouts/secure.component.ts
/layouts/secure.component.html

&

/layouts/public.component.ts
/layouts/public.component.html

from this point I can divert my routes to one of the two layouts depending if the page is meant to be secure or public. I do this by creating a route to each layout in my root routes.ts file.

/app.routes.ts

const APP_ROUTES: Routes = [
    { path: '', redirectTo: '/home', pathMatch: 'full', },
    { path: '', component: PublicComponent, data: { title: 'Public Views' }, children: PUBLIC_ROUTES },
    { path: '', component: SecureComponent, canActivate: [Guard], data: { title: 'Secure Views' }, children: SECURE_ROUTES }
];

Notice that I register my child routes for each layout. That is the exported value of each separate route file. One is in the public directory and one is in the secure directory.

/public/public.routes.ts

export const PUBLIC_ROUTES: Routes = [
    { path: '', redirectTo: 'home', pathMatch: 'full' },
    { path: 'p404', component: p404Component },
    { path: 'e500', component: e500Component },
    { path: 'login', component: LoginComponent },
    { path: 'register', component: RegisterComponent },
    { path: 'home', component: HomeComponent },
    { path: 'benefits', component: BenefitsComponent },
    { path: 'services', component: ServicesComponent },
    { path: 'education', component: EducationComponent },
    { path: 'products', component: ProductsComponent },
    { path: 'fcra', component: FcraComponent },
    { path: 'croa', component: CroaComponent },
    { path: 'building', component: BuildingComponent },
    { path: 'tips', component: TipsComponent },
    { path: 'maintenance', component: MaintenanceComponent }
];

All of these routes are now accessible as the child routes for my public layout. Which now leads us to protecting our secure views.

So in the secure directory I essentially do the same thing,

/secure/secure.routes.ts

export const SECURE_ROUTES: Routes = [
    { path: '', redirectTo: 'overview', pathMatch: 'full' },
    { path: 'items', component: ItemsComponent },
    { path: 'overview', component: OverviewComponent },
    { path: 'profile', component: ProfileComponent },
    { path: 'reports', component: ReportsComponent },
    { path: 'recommendations', component: RecommendationsComponent },
    { path: 'score-simulator', component: ScoreSimulatorComponent },
    { path: 'payment-method', component: PaymentMethodComponent },
    { path: 'lock-account', component: LockAccountComponent }
];

This allows me to use auth to protect those child routes now. If you remember in

/app.routes.ts we did this for the secure routes,

{ path: '', component: SecureComponent, canActivate: [Guard], data: { title: 'Secure Views' }, children: SECURE_ROUTES }

Notice the [Guard]. This allows us to protect all of the child routes for the secure layout. This is one reason I use child routes. I could give you a lot more but I feel this is the most reasonable explanation.

Just to take things a small step further and put this in perspective for you this is how I [Guard] the secure pages. Creating a service and implementing CanActivate

@Injectable()
export class Guard implements CanActivate {

    constructor(protected router: Router, protected auth: Auth ) {}

     canActivate() {
        if (localStorage.getItem('access_token')) {
            // logged in so return true
            return true;
        }
        // not logged in so redirect to login page
        this.router.navigate(['/home']);
        return false;
    }
}

This allows you to serve public layout with <router-outlet></router-outlet> then use a different header and footer in the layout. Then use <router-outlet></router-outlet> in the secure layout again and obviously a different header and footer. Let me know if I have left anything unclear and I will update the answer.


You can solve your problem using child routes.

See working demo at https://angular-multi-layout-example.stackblitz.io/ or edit at https://stackblitz.com/edit/angular-multi-layout-example

Set your route like below

const appRoutes: Routes = [

    //Site routes goes here 
    { 
        path: '', 
        component: SiteLayoutComponent,
        children: [
          { path: '', component: HomeComponent, pathMatch: 'full'},
          { path: 'about', component: AboutComponent }
        ]
    },

    // App routes goes here here
    { 
        path: '',
        component: AppLayoutComponent, 
        children: [
          { path: 'dashboard', component: DashboardComponent },
          { path: 'profile', component: ProfileComponent }
        ]
    },

    //no layout routes
    { path: 'login', component: LoginComponent},
    { path: 'register', component: RegisterComponent },
    // otherwise redirect to home
    { path: '**', redirectTo: '' }
];

export const routing = RouterModule.forRoot(appRoutes);