[英]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.