Переключение компонента компоновки на основе Angular 2 Guard
Так что это может быть длинный пост, но я надеюсь, что кто-то может мне помочь:)
Я создаю веб-приложение Angular 2 с "разделенной" компоновкой, то есть я буду использовать отдельный компонент компоновки в зависимости от того, прошел ли я проверку подлинности через средство защиты маршрута.
Когда я вхожу в приложение в первый раз, и у меня нет активного сеанса или файла cookie с сервера, я буду перенаправлен на страницу входа в систему, но только если эта страница защищена средством защиты маршрутизации. Эта страница входа будет переведена в "публичный" вид, который не содержит <header>
, <footer>
или же <nav>
теги в нем.
Цель этого состоит в том, чтобы иметь возможность загружать один макет HTML с <router-outlet></router-outlet>
для компонентов вида, которые требуют, чтобы пользователь вошел в систему, и имеют другой <router-outlet></router-outlet>
в другом компоненте представления, когда пользователь пытается получить доступ к "частному" маршруту.
Внутри index.html
<html>
<head></head>
<body>
<!-- Load application -->
<my-app>
<div class="vertical-wrapper center-block">
<div class="vertical-align">
<i class="fa fa-spinner fa-pulse fa-5x fa-fw"></i>
<span class="sr-only">Loading Application...</span>
</div>
</div>
</my-app>
<!-- Scripts -->
<script src="/dist/app.vendor.js"></script>
<script src="/dist/app.js"></script>
<!-- Development Server Reloading -->
<script src="/webpack-dev-server.js"></script>
</body>
</html>
Файл Routes.ts
// Required Imports.
import { Routes, RouterModule } from '@angular/router';
import { NgModule } from '@angular/core';
// Routes values
import { PUBLIC_ROUTES } from 'app/routes/public.routes';
import { PRIVATE_ROUTES } from 'app/routes/private.routes';
// Layouts
import { PublicComponent, PrivateComponent } from 'app/layouts';
// Import Pages
import { NotFoundPage } from 'app/pages';
// Guards
import { LoginGuard } from 'app/services/login.guard';
const routes: Routes = [
{
canActivate: [LoginGuard],
path: '',
component: PrivateComponent,
children: PRIVATE_ROUTES
},
{
path: '',
component: PublicComponent,
children: PUBLIC_ROUTES
},
// Greedy-route sending everything not caught to 404 page.
{ path: '**', component: NotFoundPage }
];
@NgModule({
imports: [
RouterModule.forRoot(routes)
],
exports: [RouterModule]
})
export class RoutingModule { }
Затем внутри своих приватных и общедоступных компонентов я помещаю свои "дочерние" маршруты, просто чтобы поддерживать чистоту своего приложения.
Файл приватных маршрутов
import { StartPage, ListComponent } from 'app/pages';
export const PRIVATE_ROUTES = [
{
path: '',
component: StartPage
},
{
path: 'start',
component: StartPage
},
{
path: 'lists',
component: ListComponent
}
];
Файл открытых маршрутов
import { LoginPage, LogoutPage } from 'app/pages';
export const PUBLIC_ROUTES = [
{
path: 'login',
component: LoginPage
},
{
path: 'logout',
component: LogoutPage
}
];
Я загружаю приватный или публичный компонент в зависимости от того, пытается ли пользователь получить доступ к странице, которая находится под охраной или нет.
Теперь к финальной части. Внутри моей папки "раскладки" у меня есть оба private.component.html
и public.component.html
оба содержат <router-outlet></router-outlet>
,
Частный компонент HTML
<div id="page-wrapper" [ngClass]="{'toggled': ShowNavigation}">
<div id="navigation-wrapper">
<navigation></navigation>
</div>
<div id="content-wrapper">
<header class="col-xs-12 fixed-height-60" style="border-bottom: 2px solid #92A92A">
<div class="pull-right vertical-wrapper">
<div class="vertical-align padding-right-x1">
<span class="col-sm-12 hidden-xs text-right">{{CurrentUser.userDisplayName}}</span>
<span class="col-sm-12 hidden-xs text-right">{{CurrentUser.clientDescription}}</span>
</div>
<div class="vertical-align image-wrapper">
<div class="col-sm-12 col-xs-9 pull-xs-right">
<div class="row">
<img class="image" [src]="BrandingLogo" alt="Banding logo" />
</div>
</div>
</div>
</div>
</header>
<section class="col-xs-12">
<router-outlet></router-outlet>
</section>
</div>
</div>
Публичный компонент html
<div class="container-fluid">
<div class="row">
<router-outlet></router-outlet>
</div>
</div>
У меня вопрос, как мне зарегистрировать маршрутных детей, которые должны быть доступны только в том случае, если охрана маршрута это позволяет? Мне нужно иметь возможность переключать макет, потому что только внутри самого приложения вы сможете просматривать <nav>
например.
Я знаю, что это не лучший способ сделать это, но именно так мне удалось это решить. Не стесняйтесь вносить вклад во все, что может помочь мне улучшить это.
- Есть ли хороший способ сделать это?
- Я на правильном пути, или я полностью потерял это?
Я обеспечу вас охраной, если кому-то из вас это тоже понадобится.
import { Inject, Injectable } from '@angular/core';
import { LoginService } from 'app/services/login.service';
import {
CanActivate,
Router,
RouterStateSnapshot,
ActivatedRouteSnapshot
} from '@angular/router';
@Injectable()
export class LoginGuard implements CanActivate {
constructor(
@Inject(LoginService) private loginService: LoginService,
@Inject(Router) private router: Router
) { }
canActivate( activatedRoute: ActivatedRouteSnapshot,
routerState: RouterStateSnapshot ): boolean {
if (this.loginService.User)
return true;
this.router.navigate(['/login', { redirect: routerState.url.substr(1) }]);
return false;
}
}
Вот обзор моего исходного дерева
Не стесняйтесь спрашивать меня, если я не достаточно ясно.