在角度4中为不同页面设置不同布局的最佳方法

时间:2017-10-02 14:42:58

标签: angular angular-routing angular-template angular-router

我是角色4的新手。我想要实现的是为我的应用中的不同页面设置不同的布局页眉和页脚。我有三种不同的情况:

  1. 登录,注册页面(无页眉,无页脚)
  2. 路线:['登录','注册']

    1. 营销网站页面(这是根路径,它有一个页眉和页脚,大多数这些部分在登录前出现)
    2. 路线:['','关于','联系']

      1. 应用程序登录页面(我在此部分中为所有应用程序页面设置了不同的页眉和页脚,但此页眉和页脚与市场营销网站页眉和页脚不同)
      2. 路线:['仪表板','个人资料']

        我通过在我的路由器组件html中添加页眉和页脚来临时运行该应用程序。

        请告诉我一个更好的方法。

        这是我的代码:

        应用\ 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>
        

        应用程序/家庭/ home.component.html

        <site-header></site-header>
        <div class="container">
            <p>Here goes my home html</p>
        </div>
        <site-footer></site-footer>
        

        应用程序/约/ about.component.html

        <site-header></site-header>
        <div class="container">
            <p>Here goes my about html</p>
        </div>
        <site-footer></site-footer>
        

        应用程序/登录/ login.component.html

        <div class="login-container">
            <p>Here goes my login html</p>
        </div>
        

        应用程序/仪表板/ dashboard.component.html

        <app-header></app-header>
        <div class="container">
            <p>Here goes my dashboard html</p>
        </div>
        <app-footer></app-footer>
        

        我在堆栈溢出时看到this question,但我没有从该答案中得到清晰的图片

4 个答案:

答案 0 :(得分:93)

您可以使用子路线解决问题。

https://angular-multi-layout-example.stackblitz.io/查看工作演示或在https://stackblitz.com/edit/angular-multi-layout-example

进行编辑

设置您的路线如下

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);

答案 1 :(得分:9)

你可以使用孩子,例如

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和AdminComponent,如

<app-header-main></app-header-main>
<router-outlet></router-outlet>
<app-footer-main></app-footer-main>

关于在不同文件中分离路线的帖子

答案 2 :(得分:1)

在某些情况下,布局和共享元素实际上与路由结构不匹配,或者某些元素必须根据每个路由隐藏/显示。对于这种情况,我可以考虑以下策略(让我们以app-header-main组件为例-显然,它将应用于所有共享页面元素):

输入和CSS类

您可以提供输入或CSS类来控制共享元素的内部外观,例如:

  1. <app-header-main [showUserTools]="false"></app-header-main>

  1. <app-header-main class="no-user-tools"></app-header-main>,然后使用:host(.no-user-tools)显示/隐藏需要的内容

  1. 处于路由级别(是否为子级):

    {
      path: 'home',
      component: HomeComponent,
      data: {
        header: {showUserTools: true},
      },
    },
    

并通过ActivatedRoute进行访问,例如:this.route.data.header.showUserTools

TemplateRef输入

app-header-main组件内部:

@Input() rightSide: TemplateRef<any>;

类型为TemplateRef<any>的输入,您可以在其中直接输入ng-template元素

<app-header-main [rightSide]="rightside"></app-header-main>
<ng-template #rightside>your content here</ng-template>

命名时隙包含

您可以创作app-header-main,以便它使用命名的槽位插入

在app-header-main模板内部:

<ng-content select="[rightSide]"><ng-content>

用法:

<app-header-main class="no-user-tools">
  <div rightSide>your content here</div>
</app-header-main>

答案 3 :(得分:0)

您可以通过将ng-content + ViewChild布局注入到使用该特定布局的每个页面组件中来解决该问题。

在这种常见用例中使用路由器似乎一直是我的解决方法。您想要的东西类似于Asp.Net MVC中的布局或WebForm等中的MasterPages。

在为此苦苦挣扎之后,我最终得到了这样的东西:

查看工作演示: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-不带标题

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-带标题

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';
  }
}