Beste Methode, um unterschiedliche Layouts für unterschiedliche Seiten in Winkel 4 festzulegen


75

Ich bin neu in Angular 4. Ich versuche, verschiedene Layout-Kopf- und Fußzeilen für verschiedene Seiten in meiner App festzulegen. Ich habe drei verschiedene Fälle:

  1. Anmelden, Seite registrieren (keine Kopf- und Fußzeile)

Routen: ['Login', 'Register']

  1. Marketing-Site-Seite (dies ist der Stammpfad und hat eine Kopf- und Fußzeile, meistens kommen diese Abschnitte vor der Anmeldung)

Routen: ['', 'about', 'contact']

  1. Angemeldete Seiten der App (Ich habe in diesem Abschnitt für alle App-Seiten eine andere Kopf- und Fußzeile, aber diese Kopf- und Fußzeile unterscheidet sich von der Kopf- und Fußzeile der Marketing-Site.)

Routen: ['Dashboard', 'Profil']

Ich führe die App vorübergehend aus, indem ich meiner Routerkomponente HTML eine Kopf- und Fußzeile hinzufüge.

Bitte raten Sie mir einen besseren Ansatz.

Das ist mein 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>

Ich habe diese Frage beim Stapelüberlauf gesehen, aber ich habe kein klares Bild von dieser Antwort erhalten


Dieser Link hat mehrere
Rakeshk Khanapure

Antworten:


148

Sie können Ihr Problem mithilfe von untergeordneten Routen lösen.

Siehe Arbeitsdemo unter https://angular-multi-layout-example.stackblitz.io/ oder bearbeiten Sie sie unter https://stackblitz.com/edit/angular-multi-layout-example

Stellen Sie Ihre Route wie unten ein

const appRoutes: Routes = [
    
    // Site routes goes here 
    { 
        path: '', 
        component: SiteLayoutComponent,
        children: [
          { path: '', component: HomeComponent, pathMatch: 'full'},
          { path: 'about', component: AboutComponent }
        ]
    },
    
    // App routes goes 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);

5
Demo hat wirklich sehr geholfen, ich hatte ein wenig Schwierigkeiten, dies zu verstehen, hauptsächlich konnte ich nicht bekommen, welcher leere Pfad: '' bedeutet, dass, wenn es einen Pfad gäbe: 'admin' generierte Links mit admin / profile übereinstimmen würden, aber da es leer ist Es stimmt mit den wichtigsten URL-Links wie '/ profile' überein. Wenn der untergeordnete Pfad auch der Pfad ist, stimmt es mit der Startseite überein. Es war auch nicht viel klar, was genau diese Komponenten sind: Komponenten, bei denen ich nur <router-outlet> </ router-outlet> im Original belassen und den gesamten Inhalt in neu generierten Komponenten veröffentlichen muss. Aber große tnx :)
Jiro Matchonson

1
Danke für diese Antwort. Es wurde ein Problem behoben, bei dem meine Layoutkomponente einen benannten Router hatte, der alle möglichen Probleme verursachte. Durch einfaches Entfernen funktionierte alles wie vorgesehen.
Meteorainer

1
Vielen Dank @Rameez
Srinivas

Wie funktioniert das, wenn Module träge geladen werden?
ksh

1
@AhsanAlii Vergessen Sie in einfachen Worten, wie der Browser damit umgeht. Alle Routenpfade werden durch Winkel aufgelöst. {path: '',}bedeutet nicht, dass der Pfad dort endet, er kann untergeordnete Routen haben. Wenn Sie dies jedoch verwenden {path: '',pathMatch: 'full',}, endet der Umfang Ihrer Routenebene dort. Versuchen Sie, mit der von mir freigegebenen Stack-Bits-Demo zu spielen, und führen Sie einige Experimente durch, indem Sie pathMatchzu verschiedenen Ebenen der Routendefinition wechseln.
Rameez Rami

10

Sie können Kind zB verwenden

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 und AdminComponent mögen

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

In der Post geht es darum, die Routen in verschiedenen Dateien zu trennen


Gemäß der Antwort lautet die URL "Admin / Dashboard", "Admin / Profil". Ich möchte nicht, dass dies geschieht. Ich möchte URLs als "Dashboard", "Profil" festlegen. Gibt es einen Weg dafür?
Ninja Dev

Ich möchte sagen, dass Sie, wenn Sie zwei unterschiedliche Fußzeilen haben, eine Fußzeile mit @input to und * ngIf erstellen können, um die eine oder andere Ansicht anzuzeigen, oder zwei Fußzeilen erstellen können. Jedenfalls ist es nur ein Beispiel. Sie können als "Kinder" des Pfads: '', Komponente: Hauptkomponente, Ihre Dashboard-Komponente und Profil eingeben und den Pfad vergessen: admin
Eliseo

Es ist hilfreich, wenn Sie mit Admin-Routen arbeiten. Danke, dass du mir die Idee gegeben hast.
Gurpreet Singh

1
Wie überschreibe ich Inhalte für App-Header-Main und App-Footer-Main?
Ievgen Naida

3

Es gibt Fälle, in denen das Layout und die gemeinsam genutzten Elemente nicht wirklich mit der Routing-Struktur übereinstimmen oder einige Elemente je nach Route ausgeblendet / angezeigt werden müssen. In solchen Fällen kann ich mir die folgenden Strategien vorstellen (nehmen wir ein Beispiel für eine app-header-mainKomponente - dies gilt jedoch offensichtlich für alle gemeinsam genutzten Seitenelemente):

Eingaben & CSS-Klassen

Sie können Eingaben oder CSS-Klassen bereitstellen, um das innere Erscheinungsbild Ihrer freigegebenen Elemente zu steuern, z.

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

oder

  1. <app-header-main class="no-user-tools"></app-header-main> und dann benutze: host (.no-user-tools), um zu zeigen / zu verbergen, was sein muss

oder

  1. auf Routenebene (Kind oder nicht):

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

Und ActivatedRoutewie folgt darauf zugreifen :this.route.data.header.showUserTools

TemplateRef-Eingabe

Innenkomponente app-header-main:

@Input() rightSide: TemplateRef<any>;

Eingabe vom Typ, TemplateRef<any>bei der Sie ein ng-templateElement direkt füttern können

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

Benannte Slot-Transklusion

Sie können den App-Header-Main so erstellen, dass er die benannte Slot-Transklusion verwendet

Innerhalb der App-Header-Hauptvorlage:

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

Verwendung:

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

0

Sie können das Problem lösen, indem Sie ng-content + ViewChild-Layout in jede Seitenkomponente einfügen, die dieses bestimmte Layout verwendet.

Die Verwendung des Routers für diesen allgemeinen Anwendungsfall schien mir immer eine Problemumgehung zu sein. Was Sie möchten, ähnelt Layouts in Asp.Net MVC oder MasterPages in WebForm usw.

Nachdem ich damit zu kämpfen hatte, kam ich zu so etwas:

Siehe Arbeitsdemo: 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 - ohne 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 - mit 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';
  }
}
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.