Подтвердить что ты не робот

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

  }
}

Или этот дизайн не лучший способ его решить?

4b9b3361

Ответ 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: '' }
]