92 votes

Meilleure méthode pour définir une mise en page différente pour différentes pages dans angular 4

Je suis novice en matière d'angular 4. Ce que j'essaie de faire, c'est de définir des en-têtes et des pieds de page différents pour les différentes pages de mon application. J'ai trois cas différents :

  1. Page de connexion, d'enregistrement (pas d'en-tête, pas de pied de page)

les routes : ['login', 'register']

  1. Page du site de marketing (il s'agit du chemin racine et il comporte un en-tête et un pied de page, la plupart de ces sections se trouvent avant la connexion).

routes : ['', 'about', 'contact']

  1. Pages de connexion à l'application (j'ai un en-tête et un pied de page différents dans cette section pour toutes les pages de l'application, mais cet en-tête et ce pied de page sont différents de l'en-tête et du pied de page du site de marketing).

routes : ['dashboard', 'profile']

Je lance l'application temporairement en ajoutant un en-tête et un pied de page à mon composant html de routeur.

Veuillez me conseiller une meilleure approche.

Voici mon code :

application \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>

J'ai vu cette question sur stack-overflow mais je n'ai pas obtenu une image claire de cette réponse.

171voto

Rameez Rami Points 736

Vous pouvez résoudre votre problème en utilisant des routes enfant.

Voir la démo de travail à https://angular-multi-layout-example.stackblitz.io/ ou modifier à https://stackblitz.com/edit/angular-multi-layout-example

Définissez votre itinéraire comme suit

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

10voto

Eliseo Points 4154

Vous pouvez utiliser l'enfant, par exemple

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 et AdminComponent comme

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

le post parle de séparer les routes dans des fichiers différents.

3voto

Artur Points 478

Il y a des cas où la mise en page et les éléments partagés ne correspondent pas vraiment à la structure du routage, ou certains éléments doivent être cachés/affichés en fonction du routage. Pour de tels cas, je peux penser aux stratégies suivantes (prenons un exemple de app-header-main mais il s'appliquera à tout élément de page partagé, évidemment) :

Entrées et classes css

Vous pouvez fournir des entrées ou des classes css pour contrôler l'apparence interne de vos éléments partagés, par exemple :

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

ou

  1. <app-header-main class="no-user-tools"></app-header-main> et ensuite utiliser :host(.no-user-tools) pour afficher/masquer ce qui doit l'être.

ou

  1. au niveau d'un itinéraire (enfant ou non) :

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

Et y accéder par ActivatedRoute comme ça : this.route.data.header.showUserTools

Entrée TemplateRef

À l'intérieur de app-header-main composant :

@Input() rightSide: TemplateRef<any>;

Entrée du type TemplateRef<any> où vous pourriez nourrir un ng-template élément directement

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

Transclusion d'une fente nommée

Vous pouvez créer l'app-header-main pour qu'il utilise la transclusion des slots nommés.

A l'intérieur du modèle app-header-main :

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

Utilisation :

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

0voto

Cesar Points 54

Vous pouvez résoudre le problème en utilisant l'injection de la mise en page par ng-content + ViewChild dans chaque composant de la page qui utilise cette mise en page spécifique.

Utiliser le routeur pour ce cas d'utilisation courant m'a toujours semblé être une solution de rechange. Ce que vous voulez est similaire aux Layouts dans Asp.Net MVC ou aux MasterPages dans WebForm, etc.

Après avoir lutté avec cela, j'ai fini par obtenir quelque chose comme ceci :

voir la démo de travail : 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 - sans en-tête

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 - avec en-tête

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X