Лучший способ установить разный макет для разных страниц в angular 4
Я новичок в angular 4. То, что я пытаюсь достичь, - это установить разные заголовки и нижние колонтитулы макетов для разных страниц в моем приложении. У меня три разных случая:
- Вход, регистрация страницы (без заголовка, без нижнего колонтитула)
маршруты: ['login', 'register']
- Страница маркетингового сайта (это корневой путь и имеет верхний и нижний колонтитулы, в основном эти разделы идут до входа в систему)
маршруты: ['', 'about', 'contact']
- Приложение зарегистрировано на страницах (у меня есть другой верхний и нижний колонтитулы в этом разделе для всех страниц приложения, но этот верхний и нижний колонтитулы отличаются от заголовка и нижнего колонтитула маркетингового сайта)
routes: ['dashboard', 'profile']
Я запускаю приложение временно, добавляя верхний и нижний колонтитулы к компоненту 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>
Я видел этот вопрос о переполнении стека, но я не получил четкого изображения из этого ответа
Ответы
Ответ 1
Вы можете решить свою проблему, используя дочерние маршруты.
См. Рабочую демонстрацию на 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);
Ответ 2
вы можете использовать дочерний элемент, например.
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>
сообщение о раздельном в разных файлах маршрутах
Ответ 3
Есть случаи, когда макет и общие элементы не соответствуют структуре маршрутизации, или некоторые элементы должны быть скрыты/показаны в зависимости от маршрута. Для таких случаев я могу подумать о следующих стратегиях (давайте возьмем пример компонента app-header-main
- но он, очевидно, будет применяться к любому общему элементу страницы):
Входы и классы CSS
Вы можете предоставить входные данные или классы CSS для управления внешним видом ваших общих элементов, таких как:
-
<app-header-main [showUserTools]="false"></app-header-main>
или же
-
<app-header-main class="no-user-tools"></app-header-main>
и затем используйте: host (.no-user-tools), чтобы показать/скрыть то, что должно быть
или же
-
на уровне маршрута (дочерний или нет):
{
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
элемент ng-template
<app-header-main [rightSide]="rightside"></app-header-main>
<ng-template #rightside>your content here</ng-template>
Включение именованных слотов
Вы можете создать app-header-main так, чтобы он использовал именованный слот transclusion
Внутри шаблона 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>
Ответ 4
Вы можете решить эту проблему, используя ng-content + ViewChild, вставляя макет в каждый компонент страницы, который использует этот конкретный макет.
Использование маршрутизатора для этого общего случая всегда казалось мне обходным путем. То, что вы хотите, похоже на макеты в Asp.Net MVC или MasterPages в WebForm и т.д.
После борьбы с этим у меня получилось что-то вроде этого:
см. рабочую демонстрацию: 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';
}
}