My AppModule
импортирует CoreModule
@NgModule({
providers: [
LoginService
],
})
export class CoreModule {
, который сам обеспечивает LoginService
глобально.
@Injectable()
export class LoginService {
constructor(
private router: Router,
private authService: AuthService
) { }
login(username: string, password: string) {
this.authService.login(username, password).subscribe(
response => {
this.router.navigate(['users']); // TODO Check that all router.navigate don't use hard coded strings
},
error => {
console.log(error);
}
);
}
logout() {
this.authService.logout().subscribe(
response => {
this.router.navigate(['login']);
},
error => {
console.log(error);
}
);
}
}
Существует также AuthService
, который делает серверсторона входа или выхода из системы, которая сохраняет состояние входа в систему в локальном хранилище браузера.
public isAuthenticated(): Observable<boolean> {
if (this.tokenService.accessTokenExpired()) {
if (this.tokenService.refreshTokenExpired()) {
return of(false);
} else {
return this.refreshAccessToken()
.pipe(
map(response => {
if (response) {
return true;
}
}),
catchError((error, caught) => {
return of(false);
})
);
}
}
return of(true);
}
Существует шаблон заголовка, который должен отображаться или не отображаться в зависимости от состояния входа в систему.
<mat-toolbar color="primary" *ngIf="isLoggedIn$ | async as isLoggedIn">
Этот компонент заголовка сохраняет зарегистрированное состояние.
isLoggedIn$: Observable<boolean>;
ngOnInit() {
this.isLoggedIn$ = this.authService.isAuthenticated();
}
logout(): void {
this.loginService.logout();
}
Навигация ведет себя хорошо, но шаблон заголовка нуждается в обновлении страницы для синхронизации с зарегистрированным состоянием.
ЭтоПохоже, что isLoggedIn
наблюдаемый в шаблоне заголовка не обновляется при изменении состояния входа в систему.
Код был очищен от шума.
РЕДАКТИРОВАТЬ: я обхожу проблемупропуская путь ngIf
и используя несколько макетов.
const routes: Routes = [
{
path: '',
component: LoginLayoutComponent,
children: [
{
path: '',
redirectTo: 'login',
pathMatch: 'full'
},
{
path: 'login',
component: LoginComponent
}
]
},
{
path: '',
component: HomeLayoutComponent,
canActivateChild: [AuthGuardService],
children: [
{
path: 'users',
component: UsersComponent,
},
{
path: 'detail/:id',
component: UserComponent,
},
{
path: 'dashboard',
component: DashboardComponent,
data: {
expectedRole: 'admin'
}
},
{
path: 'home',
loadChildren: './views/home/home.module#HomeModule',
data: {
preload: true,
delay: false
}
},
{
path: 'error',
component: ErrorComponent
},
]
},
];
A login
макет:
@Component({
selector: 'app-login-layout',
template: `<router-outlet></router-outlet>`
})
export class LoginLayoutComponent { }
и макет home
:
@Component({
selector: 'app-home-layout',
templateUrl: './home.layout.component.html'
})
export class HomeLayoutComponent { }
со своим шаблоном:
<mat-sidenav-container class="example-container">
<mat-sidenav #drawer mode="side" opened role="navigation">
<mat-nav-list>
<a mat-list-item routerLink='/first'>First Component</a>
<a mat-list-item routerLink='/second'>Second Component</a>
</mat-nav-list>
</mat-sidenav>
<mat-sidenav-content>
<app-header></app-header>
</mat-sidenav-content>
<router-outlet></router-outlet>
</mat-sidenav-container>