Search code examples
typescriptionic4subscribebehaviorsubjectauth-guard

Behavior subject not updating subscriber on .next(value)


I am having an issue with getting a Behavior Subject to update a subscriber on the .next(value) call.

I am new to typescript but i think i must just be missing something small. it seems correct from what i have seen.

There were quite a few issues like this on the site but none of them fixed my issue. This is an example. Subscriber doesn't receive value from .next()

RestService is only put in the app.module.ts providers array.

Auth Guard File (services/auth-guard.service.ts)


authenticated = false;

...

    ngOnInit(){
        this.restService.isLoggedIn().subscribe({
            next: result => {
                this.authenticated = result;
            }
        });
    }

...

    canActivate(route: ActivatedRouteSnapshot): boolean{

        console.log(this.authenticated);

        if(!this.authenticated){
            this.router.navigate(['login']);
        }
        return this.authenticated;
    }
}

Parts of rest service file (services/rest.service.ts)

import { HttpClient, HttpParams, HttpHeaders } from '@angular/common/http';
import { RequestOptions } from '@angular/http';
import { Injectable } from '@angular/core';
import { Storage } from  '@ionic/storage';
import { Observable, BehaviorSubject } from  'rxjs';
import { User } from  'src/app/Interfaces/user';
import { tap } from 'rxjs/operators';

...

authSubject  =  new  BehaviorSubject(false);

...

public _setAuthSubject(value){
    this.authSubject.next(value);
 }

public isLoggedIn() {
    return this.authSubject.asObservable();
  }

In canActivate I have a console log that shows that this.authenticated is always false, but if I put another subscriber call and print the other variable under this, I can see that it is actually true now and it was properly updated. Am I missing something here that causes authenticated to not be updated?

Some additional information. Here is my app.module.ts

@NgModule({
  declarations: [AppComponent],
  entryComponents: [],
  imports: [
    BrowserModule,
    IonicModule.forRoot(),
    AppRoutingModule,
    HttpClientModule,
    IonicStorageModule.forRoot()
  ],
  providers: [
    AuthGuardService,
    StatusBar,
    SplashScreen,
    { provide: RouteReuseStrategy, useClass: IonicRouteStrategy },
    SQLite,
    SQLitePorter,
    RestService,
  ],
  bootstrap: [AppComponent]
})

And also the routing that calls the auth guard service (app-routing.module.ts)

import { NgModule } from '@angular/core';
import { PreloadAllModules, RouterModule, Routes } from '@angular/router';
import { AuthGuardService } from './services/auth-guard.service';

const routes: Routes = [
  { path: '', loadChildren: './tabs/tabs.module#TabsPageModule', canActivate: [AuthGuardService]},
  { path: 'login', loadChildren: './login/login.module#LoginPageModule' },
];
@NgModule({
  imports: [
    RouterModule.forRoot(routes, { preloadingStrategy: PreloadAllModules })
  ],
  exports: [RouterModule]
})
export class AppRoutingModule { }

Lastly here is the function that is called that actually set the auth subject to true (login/login.page.ts)

constructor(
    public menu: MenuController,
    private restService: RestService,
    private router: Router,
    private storage: Storage
  ) { }


  async login(form){

    this.restService.login(form.value).subscribe({
      next: response => {
        console.log(response)
        if(response.access_token){
          this.storage.set("ACCESS_TOKEN", response.access_token);
          this.restService._setToken(response.access_token);
          this.restService._setAuthSubject(true);
        }
        this.router.navigateByUrl('');
      },
      error: err => {
        console.log('ERROR!: ', err)
      }
    });
  }

Solution

  • modified AuthGuard with the below code. Services cant have code in ngOnInit, i had no idea! Nooby mistake... thank you for all the help @ingkevin and @lchraf.

        init(){
            this.restService.isLoggedIn().subscribe({
                next: result => {
                    this.authenticated = result;
                }
            });
        }
    
        constructor(private router: Router, 
                    public restService: RestService) {
                        this.init()
                    }
    
    

    ngOnInit was removed.