[英]angular/material - how to get mat-toolbar shadow over the page content?
[英]Angular Material <mat-toolbar> hides when refresh page
我正在开发一个 Angular Material 应用程序。
我的app.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() y 有:
this.isLoggedIn$ = this.authService.isLoggedIn;
}
我遇到的问题是用户重新加载页面时。 导航栏消失。 修复它的最佳解决方案是什么? 当用户登录时,系统会在 localStorage 中保存一个令牌。 我想使用它,但我不知道如何确定 ngIf 中的条件,因为我有异步 pipe 。
提前致谢
更新这是我的 auth.Service:
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);
}
}
这是我的 app.component.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这是我的 app-routing.module.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),所以在用户重新加载页面之前一切正常
如果需要存储用户的state,则应使用本地存储。 因为每次用户重新加载页面时,一切都是从头开始重建的。
在您的组件中
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);
}
}
当用户登录和注销时,需要分别设置和清除令牌。
当然,这只是一个基本的用例。 您不必每次都调用存储,您可能希望将其设为可观察的。 用户第一次加载应用程序时,它会调用存储,将其保存在 memory 中,并在用户未刷新应用程序时重复使用。
我希望它有用:)
this.authService.isLoggedIn 是否返回 true 的 observable?
我怀疑不是。 尝试将 isLoggedIn$ 配置为 behaviorSubject 并在 ngOnInit 上调用 this.authService.isLoggedIn.next(this.authService.isLoggedIn)
isLoggedIn$ = new BehaviorSubject(false);
ngOninit() {
this.isLoggedIn$.next(this.authService.isLoggedIn);
}
另一种解决方案是不使用 | 异步并在 HTML 文件中使用:
*ngIf=authService.isLoggedIn
由于您粘贴的代码非常少......我只能给出一些我能想到的建议:
像其他人提到的那样,您应该检查是否
this.authService.isLoggedIn
总是返回一个可观察的。
关于如何确定 ngIf 中的条件:
*ngIf="isLoggedIn$| async as isLoggedIn"
您可以打印出 isLoggedIn 的值
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.