2

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)
      }
    });
  }
Imgoinghamm
  • 53
  • 1
  • 6
  • In your service you are updating authSubject and in your component you are subscribing to isLoggedIn(). what does isLoggedIn() do ? how does it relate to authSubject ? May be you can explain or add some code to your post – Ichraf Jun 03 '19 at 07:48
  • @lchraf Oh man im sorry, that would obviously help. I added that in. IsLoggedIn returns authsubject as an observable. – Imgoinghamm Jun 03 '19 at 15:39
  • I looks ok for me. I don't think the problem is the behaviour subject. It migth be your DI setup. You can check if your rest service is not being re-instatiated making your guard always have the same initial value (false). – ingkevin Jun 03 '19 at 15:57
  • I was curious about this as well. so underneath my console.log(this.authenticated);line i added another subscribe (which would subscribe every time this function gets called), the value shows true.Or do you mean auth gaurd service (the first code snippet). – Imgoinghamm Jun 03 '19 at 16:12
  • @ingkevin I am also not sure what you mean by DI setup. – Imgoinghamm Jun 03 '19 at 18:04
  • By DI I ment Dependency Injection but know that you added your module definition it also seems ok. You can try returning the `restService.isLoggedIn()` observable in your guard. By definition you can return ` Observable | Promise | boolean | UrlTree`. – ingkevin Jun 04 '19 at 03:22
  • If i understand correctly, you are saying that instead of doing the subscribe, just return the observable? – Imgoinghamm Jun 04 '19 at 04:06
  • HOOZAH I FIGURED IT OUT. its because ngOnInit does not work with services.. if i stil it in the constructor it works. I know you are supposed to keep logic out of the constructer but services I guess makes it okay. – Imgoinghamm Jun 04 '19 at 05:15

2 Answers2

1

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.

Imgoinghamm
  • 53
  • 1
  • 6
1

I have created a demo on BehaviourSubject please have a look might be helpful to solve your issue.

https://stackblitz.com/edit/behavioursubject-angular-demo