I am new to angular 4. What I'm trying to achieve is to set different layout headers and footers for different pages in my app. I have three different cases:
- Login, register page (no header, no footer)
routes: ['login','register']
- Marketing site page (this is the root path and it has a header and footer, mostly these sections come before login)
routes : ['','about','contact']
- App logged in pages (I have a different header and footer in this section for all the app pages but this header and footer is different from the marketing site header and footer)
routes : ['dashboard','profile']
I run the app temporarily by adding a header and footer to my router component html.
Please advise me a better approach.
This is my code:
app\app.routing.ts
const appRoutes: Routes = [
{ path: '', component: HomeComponent},
{ path: 'about', component: AboutComponent},
{ path: 'contact', component: ContactComponent},
{ path: 'login', component: LoginComponent },
{ path: 'register', component: RegisterComponent },
{ path: 'dashboard', component: DashboardComponent },
{ path: 'profile', component: ProfileComponent },
// otherwise redirect to home
{ path: '**', redirectTo: '' }
];
export const routing = RouterModule.forRoot(appRoutes);
app.component.html
<router-outlet></router-outlet>
app/home/home.component.html
<site-header></site-header>
<div class="container">
<p>Here goes my home html</p>
</div>
<site-footer></site-footer>
app/about/about.component.html
<site-header></site-header>
<div class="container">
<p>Here goes my about html</p>
</div>
<site-footer></site-footer>
app/login/login.component.html
<div class="login-container">
<p>Here goes my login html</p>
</div>
app/dashboard/dashboard.component.html
<app-header></app-header>
<div class="container">
<p>Here goes my dashboard html</p>
</div>
<app-footer></app-footer>
I saw this question on stack-overflow but i didn't get a clear picture from that 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);
you can use child e.g.
const appRoutes: Routes = [
{ path: '', component: MainComponent,
children:{
{ path: 'home' component:HomeComponent},
{ path: 'about', component: AboutComponent},
{ path: 'contact', component: ContactComponent},
..others that share the same footer and header...
}
},
{ path: 'login', component: LoginComponent },
{ path: 'register', component: RegisterComponent },
{ path: 'admin', component:AdminComponent,
children{
{ path: 'dashboard', component: DashboardComponent },
{ path: 'profile', component: ProfileComponent }
..others that share the same footer and header...
}
}
{ path: '**', redirectTo: '' }
];
MainComponent and AdminComponent like
<app-header-main></app-header-main>
<router-outlet></router-outlet>
<app-footer-main></app-footer-main>
the post talk about separate in diferent files the routes
There are cases where the layout and shared elements don't really match the routing structure, or some elements have to be hidden/shown depending on a per-route basis. For such cases I can think of the following strategies (let's take an example of app-header-main
component - but it will apply to any shared page element obviously):
Inputs & css classes
You can provide inputs or css classes to control the inner appearance of your shared elements, such as:
<app-header-main [showUserTools]="false"></app-header-main>
or
<app-header-main class="no-user-tools"></app-header-main>
and then use :host(.no-user-tools) to show/hide what needs to be
or
at a route level (child or not):
{ path: 'home', component: HomeComponent, data: { header: {showUserTools: true}, }, },
And access it through ActivatedRoute
like so: this.route.data.header.showUserTools
TemplateRef input
Inside app-header-main
component:
@Input() rightSide: TemplateRef<any>;
Input of type TemplateRef<any>
where you could feed an ng-template
element directly
<app-header-main [rightSide]="rightside"></app-header-main>
<ng-template #rightside>your content here</ng-template>
Named slot transclusion
You can author the app-header-main so that it uses named slot transclusion
Inside of app-header-main template:
<ng-content select="[rightSide]"><ng-content>
Usage:
<app-header-main class="no-user-tools">
<div rightSide>your content here</div>
</app-header-main>
You can solve the problem using ng-content + ViewChild injection of layout into each page component that uses that specific layout.
Using the router for this common use case always seemed like a workaround to me. What you want is similar to Layouts in Asp.Net MVC or MasterPages in WebForm etc.
After struggling with this I ended up with something like this:
see working demo: https://stackblitz.com/edit/angular-yrul9f
shared.component-layout.ts
import { Component } from '@angular/core';
@Component({
selector: 'shared-component-layout',
template: `
<div *ngIf="!hideLayoutHeader" style="font-size: 2rem;margin-bottom: 10px;">
Layout title: {{layoutHeader}}
<ng-content select=".layout-header">
</ng-content>
</div>
<ng-content select=".layout-body">
</ng-content>
`
})
export class SharedComponentLayout {
layoutHeader: string;
hideLayoutHeader: boolean;
}
page.component-base.ts
import { Component, ViewChild } from '@angular/core';
import { SharedComponentLayout } from './shared.component-layout';
export abstract class PageComponentBase {
@ViewChild('layout') protected layout: SharedComponentLayout;
}
login.component.ts - without header
import { Component } from '@angular/core';
import { PageComponentBase } from './page.component-base';
@Component({
selector: 'login-component',
template: `
<shared-component-layout #layout>
<div class="layout-body">
LOGIN BODY
</div>
</shared-component-layout>
`
})
export class LoginComponent extends PageComponentBase {
ngOnInit() {
this.layout.hideLayoutHeader = true;
}
}
home.component.ts - with header
import { Component } from '@angular/core';
import { PageComponentBase } from './page.component-base';
@Component({
selector: 'home-component',
template: `
<shared-component-layout #layout>
<div class="layout-body">
HOME BODY
</div>
</shared-component-layout>
`
})
export class HomeComponent extends PageComponentBase {
ngOnInit() {
this.layout.layoutHeader = 'Home component header';
}
}
来源:https://stackoverflow.com/questions/46527826/best-method-to-set-different-layout-for-different-pages-in-angular-4