我正在开发一个Angular Material应用程序。
我在myapp.component.html:中有这个垫子工具栏
<mat-toolbar color="primary" *ngIf="isLoggedIn$ | async" fullscreen>
<button mat-icon-button (click)="sidenav.toggle()"><mat-icon>menu</mat-icon></button>
<h1>SAP</h1>
</mat-toolbar>
<mat-sidenav-container [style.marginTop.px]="mobileQuery.matches ? 56 : 0">
<mat-sidenav #sidenav [mode]="mobileQuery.matches ? 'over' : 'side'"
[fixedInViewport]="mobileQuery.matches">
<mat-nav-list>
<a mat-list-item *ngIf="isOp==false" (click)="sidenav.toggle()" routerLink="/trafos">
<mat-icon svgIcon="fohama"></mat-icon> <span class="nav-caption"> Transformadores</span>
</a>
<a mat-list-item *ngIf="isOp==false" (click)="sidenav.toggle()" routerLink="/empleados">
<mat-icon>assignment_ind</mat-icon> <span class="nav-caption"> Empleados</span>
</a>
<a mat-list-item *ngIf="isOp==false" (click)="sidenav.toggle()" routerLink="/clientes">
<mat-icon>assignment_ind</mat-icon> <span class="nav-caption"> Clientes</span>
</a>
<a mat-list-item *ngIf="isOp==false" (click)="sidenav.toggle()" routerLink="/procesos">
<mat-icon>settings</mat-icon> <span class="nav-caption"> Procesos</span>
</a>
<a mat-list-item *ngIf="isOp==false" (click)="sidenav.toggle()" routerLink="/modificarProcesos">
<mat-icon>edit</mat-icon> <span class="nav-caption"> Modificar Procesos</span>
</a>
<a mat-list-item *ngIf="isOp==false" (click)="sidenav.toggle()" routerLink="/order">
<mat-icon>low_priority</mat-icon> <span class="nav-caption"> Priorizar Transformadores</span>
</a>
<a mat-list-item *ngIf="isOp==false" (click)="sidenav.toggle()" routerLink="/referencias">
<mat-icon>add_comment</mat-icon> <span class="nav-caption"> Referencias</span>
</a>
<a mat-list-item *ngIf="isOp==false" (click)="sidenav.toggle()" routerLink="/reportes">
<mat-icon>insert_chart_outlined</mat-icon> <span class="nav-caption"> Reportes</span>
</a>
<a mat-list-item (click)="sidenav.toggle()" (click)="logout()">
<mat-icon>exit_to_app</mat-icon><span class="nav-caption"> logout</span>
</a>
</mat-nav-list>
</mat-sidenav>
<mat-sidenav-content>
<router-outlet></router-outlet>
</mat-sidenav-content>
</mat-sidenav-container>
一切都很好。这个栏在应用程序组件中,ngOnInit((有这个:
this.isLoggedIn$ = this.authService.isLoggedIn;
}
我遇到的问题是当用户重新加载页面时。导航栏消失。修复它的最佳解决方案是什么?当用户登录时,系统会在localStorage中保存一个令牌。我想使用它,但我不知道如何确定ngIf中的条件,因为我在其中有异步管道。
提前感谢
更新这是我的授权。服务:
export class AuthService {
apiUrl = `${environment.baseUrl}/auth`;
message:string;
durationInSeconds:1;
isOp:boolean=true;
sector:number=0;
private loggedIn = new BehaviorSubject<boolean>(false);
userChange$ = new BehaviorSubject({isOp: null, sector: null});
get isLoggedIn() {
return this.loggedIn.asObservable();
}
constructor(private http:HttpClient,private _snackBar: MatSnackBar,private router:Router) { }
login(data: any): Observable<any> {
return this.http.post<any>(`${this.apiUrl}/login`, data)
.pipe(
tap(_ =>
{
//console.log(_);
this.openSnackBar("Sesión iniciada");
this.loggedIn.next(true);
this.userChange(_.isOp,_.sector);
this.isOp=_.isOp;
this.sector=_.sector;
//localStorage.setItem("sector",_.sector);
//localStorage.setItem("isOp",_.isOp);
}
),
catchError(this.handleError('login Failed', ))
);
}
userChange(isOp, sector){
this.userChange$.next({
isOp: isOp,
sector: sector
});
}
isLogged(){
if(localStorage.getItem('sector'))
{
this.loggedIn.next(true);
}
}
logout(){
this.router.navigate(['/login']);
localStorage.clear();
this.loggedIn.next(false);
}
}
这是我的应用程序组件。ts:
export class AppComponent implements OnInit {
title = 'client';
isOp:boolean;
sector:number;
isLoggedIn$: Observable<boolean>;
// isLogged$:Observable<boolean>;
//usDetail:Observable<Object>;
mobileQuery: MediaQueryList;
private _mobileQueryListener: () => void;
constructor(changeDetectorRef: ChangeDetectorRef, media: MediaMatcher,private router: Router,private matIconRegistry: MatIconRegistry,sanitizer: DomSanitizer,private authService:AuthService,private mensajesService:MensajesService) {
this.mobileQuery = media.matchMedia('(max-width: 600px)');
this._mobileQueryListener = () => changeDetectorRef.detectChanges();
this.mobileQuery.addListener(this._mobileQueryListener);
this.matIconRegistry.addSvgIcon(
'fohama',
sanitizer.bypassSecurityTrustResourceUrl('assets/logofohamaico.svg')
);
}
ngOnInit() {
// this.isLogged=localStorage.getItem('token');
//console.log(this.isLogged);
// this.isLogged$ = this.tokenInterceptor.isLogged;
this.isLoggedIn$ = this.authService.isLoggedIn;
console.log("")
this.mensajesService.getMessage().subscribe(res=>{
console.log("Respuesta: ",res);
this.isOp=res.isOp;
})
ngOnDestroy(): void {
this.mobileQuery.removeListener(this._mobileQueryListener);
}
logout() {
this.authService.logout();
}
更新2这是我的应用程序例程模块.ts
const routes: Routes = [
{path:'login',component:LoginComponent,data:{title:'Login'}},
{path:'register',component:RegisterComponent,data:{title:'Registro'}},
{path:'',component:LoginComponent},
{path:'reportes',component:DailyReportComponent,canActivate:[GuardianGuard]},
{path: 'empleados', component:EmpleadosComponent,canActivate:[GuardianGuard]},
{path: 'clientes',component:ClientesComponent,canActivate:[GuardianGuard] },
{path:'procesos',component:TimerReloadedComponent,canActivate:[GuardianGuard]},
{path:'modificarProcesos',component:ModificarProcesosComponent,canActivate:[GuardianGuard]},
{path:'order',component:OrderComponent,canActivate:[GuardianGuard]},
{path:'referencias',component:ReferenciasComponent,canActivate:[GuardianGuard]},
{path:'trafos',component:TransformadoresReloadedComponent,canActivate:[GuardianGuard]}
//{path:'**',redirectTo:'/login'}
];
登录组件:
export class LoginComponent implements OnInit {
loginForm: FormGroup;
nombreUs = '';
pass = '';
matcher = new ErrorStateMatcher();
isLoadingResults = false;
messageSnack:string;
durationInSeconds=3;
private us = new BehaviorSubject<Object>("");
get usDetail() {
return this.us.asObservable();
}
constructor(private formBuilder: FormBuilder, private router: Router, private authService: AuthService,private _snackBar: MatSnackBar, private mensajeService:MensajesService) { }
ngOnInit() {
this.loginForm = this.formBuilder.group({
'nombreUs' : [null, Validators.required],
'pass' : [null, Validators.required]
});
}
onFormSubmit(form: NgForm) {
this.authService.login(form)
.subscribe(res => {
//console.log(res);
if(res){
this.mensajeService.enviarMensaje({
isOp:res.isOp,
sector:res.sector
})
this.us.next({isOp:res.isOp,sector:res.sector});
if (res.token) {
localStorage.setItem('token', res.token);
}
if(res.isOp==true)
{
this.router.navigate(['procesos']);
}
else{
this.router.navigate(['trafos']);
}
}
else{
this.openSnackBar("Usuario o contraseña inválidos");
}
}, (err) => {
// this.openSnackBar("Usuario o contraseña inválidos");
console.log(err);
});
}
openSnackBar(mensaje) {
this._snackBar.open(mensaje,"mensaje", {
duration: this.durationInSeconds * 1000,
});
}
login(){
this.router.navigate(['transformadores'])
}
register() {
this.router.navigate(['register']);
}
}
//Managing form validation
export class MyErrorStateMatcher implements ErrorStateMatcher {
isErrorState(control: FormControl | null, form: FormGroupDirective | NgForm | null): boolean {
const isSubmitted = form && form.submitted;
return !!(control && control.invalid && (control.dirty || control.touched || isSubmitted));
}
}
所以,因为这个工具栏在app.component中;主页";是登录组件(调用auth.Service(,在用户重新加载页面之前,一切都很好
如果需要存储用户的状态,应该使用本地存储。因为每次用户重新加载页面时,一切都是从头开始重建的。
在组件中
this.isLoggedIn = this.authService.isAuthenticated();
在您的身份验证服务中
import { StorageService } from './storage.service';
@Injectable({
providedIn: 'root',
})
export class AuthService {
isLoggedIn$ = new BehaviorSubject(false);
constructor(private localStorage: StorageService) {
this.isLoggedIn$.next(this.checkSessionStorage());
}
public login(...) {
// make the request
this.storageService.setToken(a_Token);
this.isLoggedIn$.next(true);
}
public logout() {
this.storageService.clearToken();
this.isLoggedIn$.next(false);
}
public checkSessionStorage(): boolean {
return this.localStorage.getToken() !== null;
}
public isAuthenticated(): Obseravable<boolean> {
return this.isLoggedIn$.asObservable();
}
}
在您的存储服务中
import { Injectable } from '@angular/core';
import { LocalStorageService } from 'ngx-webstorage';
const TOKEN = 'token';
@Injectable({
providedIn: 'root',
})
export class StorageService {
constructor(private localStorageService: LocalStorageService) { }
getToken(): string {
return this.localStorageService.retrieve(TOKEN);
}
setToken(token: string): void {
this.localStorageService.store(TOKEN, token);
}
clearToken() {
this.localStorageService.clear(TOKEN);
}
}
当用户登录和注销时,您需要分别设置和清除令牌。
当然,这只是一个基本的用例。您不必每次都调用存储,您可能希望将其作为可观察对象。用户第一次加载应用程序时,它会调用存储,将其保存在内存中,并在用户没有刷新应用程序时重用它。
我希望它能有用:(
由于粘贴的代码非常少。。。到目前为止,我只能给出一些我能想到的建议:
-
像前面提到的其他人一样,你应该检查
this.authService.isLoggedIn
总是返回一个oberservable。
-
关于如何确定ngIf:中的条件
*ngIf="isLoggedIn$| async as isLoggedIn"
您可以在中打印出isLoggedIn的值
this.authService.isLoggedIn是否返回true的可观测值?
我怀疑不是。尝试将isLoggedIn$配置为behaviorSubject,并在ngOnInit上调用this.authService.isLoggedIn.next(this.authServices.isLoggerIn(
isLoggedIn$ = new BehaviorSubject(false);
ngOninit() {
this.isLoggedIn$.next(this.authService.isLoggedIn);
}
另一个解决方案是不使用|async,而在HTML文件中使用:
*ngIf=authService.isLoggedIn