Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Multiple layouts for different pages in Angular 2

Tags:

angular

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?

like image 824
baaroz Avatar asked Nov 09 '16 13:11

baaroz


3 Answers

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.

like image 163
wuno Avatar answered Nov 19 '22 13:11

wuno


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);
like image 31
Rameez Rami Avatar answered Nov 19 '22 13:11

Rameez Rami


You can have multiple router-outlet and redirect where you want. For example login page can be the landing page if user is not logged in and if use is logged in you redirect user to a master page where you have header and footer and all other pages can be child of that component. For example we have our app like this

<my-app></my-app>

in my-component you have a

<router-outlet></router-outlet> ¨ you have one login component and you can use that routing for that page like this

 { path: '', component: LoginComponent}

as told earlier this can be landing page and you don't want to show anything else then login details. Once user sign in you redirect user to master component and master component will have routing like this

{ path: 'masterpage', component: MasterComponent}

and master component will have router outlet as well

<router-outlet></router-outlet>

now when you want to show user other pages like about us. then you will redirect user to about us page like this

{ canActivate: [AuthGuard], component: MasterComponent , path: 'masterpage',
  children:[
           {   canActivate: [AuthGuard],
               component: AboutUsComponent ,
               path: 'aboutus'
           }]
}

and this way you will have details like header and footer every where use navigate. I hope this helps!

like image 2
Jorawar Singh Avatar answered Nov 19 '22 14:11

Jorawar Singh