簡體   English   中英

Angular材料<mat-toolbar>刷新頁面時隱藏</mat-toolbar>

[英]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">&nbsp;  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">&nbsp;  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">&nbsp;  Clientes</span>   
            </a>
            <a mat-list-item *ngIf="isOp==false" (click)="sidenav.toggle()" routerLink="/procesos">
                <mat-icon>settings</mat-icon> <span class="nav-caption">&nbsp;  Procesos</span>   
            </a>
            <a mat-list-item *ngIf="isOp==false" (click)="sidenav.toggle()" routerLink="/modificarProcesos">
                <mat-icon>edit</mat-icon> <span class="nav-caption">&nbsp;  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">&nbsp;  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">&nbsp;  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">&nbsp;  Reportes</span>   
            </a>

            <a mat-list-item (click)="sidenav.toggle()" (click)="logout()">
                <mat-icon>exit_to_app</mat-icon><span class="nav-caption">&nbsp;  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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM