Angular2: Использование маршрутов, как отобразить навигационную панель после успешного входа в систему?
Я пытаюсь показать панель навигации, как только пользователь успешно выполнит.
Например:
Как изменить свойство showMenu в "AppComponent" внутри "LoginComponent"? Важно: я использую маршруты.
app.ts:
@Component({
selector: 'app',
template: `<div *ngIf="showMenu">
<fnd-menu-nav></fnd-menu-nav>
</div>
<router-outlet></router-outlet>
`,
directives: [ROUTER_DIRECTIVES, MenuNavComponent]
})
@RouteConfig([
{ path: '/login', name: 'Login', component: LoginComponent, useAsDefault: true },
{ path: '/welcome', name: 'Welcome', component: WelcomeComponent }
])
export class AppComponent {
public showMenu : boolean;
}
login.component.ts:
@Component({
selector: 'fnd-login',
templateUrl: './fnd/login/components/login.component.html',
providers: [LoginService]
})
export class LoginComponent {
/* .. other properties */
constructor(private _router: Router, private _loginService: LoginService ) {
}
/* .. other methods */
/* .. other methods */
private onLoginSuccessfully(data : any) : void {
/* --> HERE: Set showMenu in AppComponent to true. How? */
this._router.navigate(['Welcome']);
}
}
Или этот дизайн не лучший способ его решить?
Ответы
Ответ 1
Недавно я сделал нечто подобное, и вот как я это сделал. Во-первых, вам нужно создать NavBarComponent в корне вашего приложения. И в NavBarComponent вы ссылаетесь (то, что я называю) на GlobalEventsManager, который является сервисом, который вы вводите там, где вам это нужно.
Вот посмотрите на GlobalEventsManager:
import { Injectable } from '@angular/core';
import { BehaviorSubject } from "rxjs/BehaviorSubject";
import { Observable } from "rxjs/Observable";
@Injectable()
export class GlobalEventsManager {
private _showNavBar: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
public showNavBarEmitter: Observable<boolean> = this._showNavBar.asObservable();
constructor() {}
showNavBar(ifShow: boolean) {
this._showNavBar.next(ifShow);
}
}
Ответ 2
На самом деле существует совершенно другой подход, который не использует ни один из излучателей/слушателей событий. Я ничего не имею против событий, и я использую оба подхода (ниже один и @brando один) в соответствии с конкретными потребностями проекта/сложностью.
Метод: у нас есть 2 прикладных модуля (области): public (у которых нет navbar) и защищен (тот, который имеет один).
Открытый модуль содержит все общедоступные маршруты:
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { RouterModule } from '@angular/router';
import { LoginComponent } from './login/login.component';
import { RegistrationComponent } from './registration/registration.component';
import { ResetPasswordComponent } from './reset-password/reset-password.component';
@NgModule({
imports: [
CommonModule,
RouterModule.forChild([
{ path: 'login', component: LoginComponent },
{ path: 'registration', component: RegistrationComponent },
{ path: 'reset-password', component: ResetPasswordComponent }
])
],
declarations: [
LoginComponent,
RegistrationComponent,
ResetPasswordComponent
]
})
export class PublicModule { }
Это то, что у вас уже было, нет ничего необычного здесь.
Тогда у нас есть защищенная область
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { RouterModule } from '@angular/router';
import { NavbarWrapperComponent } from './navbar-wrapper/navbar-wrapper.component';
import { UserProfileComponent } from './user-profile/user-profile.component';
@NgModule({
imports: [
CommonModule,
RouterModule.forChild([
{ path: '', redirectTo: '/login', pathMatch: 'full' }, // point 1
{
path: '', // point 2
component: NavbarWrapperComponent, // point 3
children: [
{ path: 'profile', component: UserProfileComponent }
]
}
])
],
declarations: [
NavbarWrapperComponent,
UserProfileComponent
]
})
export class ProtectedModule { }
и здесь начинается магия.
Прежде всего, обратите внимание на точку 1:
{ path: '', redirectTo: '/login', pathMatch: 'full' },
Нам нужен этот прямо здесь. Если мы поместим его в AppModule, он будет проигнорирован. Здесь нет ничего важного, возможно, было бы еще более логично иметь эту переадресацию в защищенном модуле.
Точка 2 позволяет проксировать все маршруты детей в NavbarWrapperComponent
(пункт 3), которая заботится о рендеринге всех наших детей. Вот шаблон компонента navbar:
<nav class="navbar navbar-toggleable-md navbar-light bg-faded">
<!-- nav content here -->
</nav>
<router-outlet></router-outlet>
Этот <router-outlet>
будет обрабатывать все маршруты для детей.
Возможные проблемы, с которыми вы можете столкнуться, и их решение:
- вам может потребоваться перенаправить на
AppModule
- просто измените путь в точке 2 на какое-то настоящее имя, например. protected
. Это будет префикс для всех ваших защищенных URL-адресов с этим значением, которое вам может не понадобиться. У вас есть 2 варианта выбора.
- вы можете иметь не только один модуль внутри защищенной области - просто используйте ленивую маршрутизацию
- вы можете скрыть/показать навигацию, параметры передачи и т.д. - просто объединить ее с решением событий.
Этот способ может показаться не таким гибким, однако он действительно работает и охватывает почти все случаи, которые могут вам понадобиться. Он не имеет сложности событий и полностью использует функции Router
. Убийца здесь - это глупо, просто и очень легко понять и поддерживать.
Ответ 3
лучший современный способ в angular4, с новым маршрутизатором, с детскими маршрутами, просто нужно использовать UrlSerializer-класс для удаления скобок, https://angular.io/docs/ts/latest/api/router/index/UrlSerializer-class.html,
кто-нибудь его использовал?
export const ROUTES: Routes = [
{ path: 'login', component: LoginComponent },
{
path : '',
children: [
{
path: '', component: DefaultLayoutComponent,
children: [
{ path: '', component: HomeComponent, canActivate: [AuthGuard] },
{ path: 'users', component: UsersListComponent, canActivate: [AuthGuard] },
{ path: 'users-add', component: UsersAddComponent, canActivate: [AuthGuard] },
{ path: 'users-view/:id', component: UsersViewComponent, canActivate: [AuthGuard] },
{ path: 'users-edit/:id', component: UsersEditComponent, canActivate: [AuthGuard] },
]
}
]
},
// otherwise redirect to home
{ path: '**', redirectTo: '' }
]