0

I'm sorry if my question looks silly.

I try to implement behaviorsubject in my service and then call it from my login component.

This is my service

private currentTokenSubject: BehaviorSubject<AuthResponse>;
  public currentToken: Observable<AuthResponse>;

constructor(private httpClient: HttpClient) {
    this.currentTokenSubject = new BehaviorSubject<any>(localStorage.getItem(TOKEN_NAME));
    this.currentToken = this.currentTokenSubject.asObservable();
  }

public get currentTokenValue(): AuthResponse {
    // console.log('auth service: ' + this.currentTokenSubject.value)
    return this.currentTokenSubject.value;
  }

  login(usernameOrEmail:string, password: string){
    return this.httpClient.post<any>(this._loginUrl,{usernameOrEmail, password})
      .pipe(map(res => {
        //login sucess if there's jwt token in the response
        if(res && res.accessToken){
          //store user details and jwt token in local storage to keep user logged in between page refresh
          localStorage.setItem(TOKEN_NAME, res.accessToken);
          this.currentTokenSubject.next(res.accessToken);
          console.log(this.currentTokenValue); // It's changed
        }
        return res;
      }));
  }

here the code in my component

constructor(
    private formBuilder: FormBuilder, 
    private authService: AuthService, 
    private router: Router,
    private route: ActivatedRoute,
    private alertService: AlertService
    ) {
      this.returnUrl = this.route.snapshot.queryParams['returnUrl'] || '';

      if(this.authService.currentTokenValue){
        this.router.navigate([this.returnUrl]);
      }
  }

onSubmit(): void{
    for (const i in this.loginForm.controls) {
      this.loginForm.controls[i].markAsDirty();
      this.loginForm.controls[i].updateValueAndValidity();
    }

    // stop here if form is invalid
    if (this.loginForm.invalid) {
      return;
    }

    const val = this.loginForm.value;
    this.isLoading = true;

    this.authService.login(val.username, val.password) // calls the service
      .pipe(first())
      .subscribe( 
        data => {
          setTimeout(() => {this.router.navigate([this.returnUrl])},500);
        },
        error => {
          this.alertService.error(error);
          this.isLoading = false;
        }
    );
  }

And this is the guard

constructor(
    private router: Router,
    private authService: AuthService
  ){}

  canActivate( next: ActivatedRouteSnapshot, state: RouterStateSnapshot
  ) {
    const currentToken = this.authService.currentTokenValue;
    console.log(currentToken); // return null
    if(currentToken){
      //authorized
      return true;
    }


    // not logged in : redirect to login page with return url
    //console.log(state.url)
    this.router.navigate(['login'], { queryParams : { returnUrl: state.url }});
    return false;
  }

when I tried to login console.log in the guard returns null.

Anyone can explain to me, why is it like that?

UPDATE

Nothing wrong with the application, what you must do is:

ONLY USE PROVIDERS ONCE

Import the service to @ngmodule in app.module.ts, otherwise you will create instance each component / module.

Ahfa
  • 180
  • 8

2 Answers2

0

You need to use .getValue() on the BehaviourSubject if you want to read the current value rather than .value

public get currentTokenValue(): AuthResponse {
    return this.currentTokenSubject.getValue();
}
Ralpharoo
  • 789
  • 9
  • 21
  • still not working, my doubt is the guard calling the same authservice instance?? – Ahfa Dec 05 '19 at 04:28
  • @AhmadFaruk based on the code you've provided, yes it is calling the same service. These services are singletons and are therefore able to be shared across other services / components. If .getValue() is not returning the set token, you will need some other console.log()s (or use Chromes Debugger) to trace and ensure your .next() is setting the value. – Ralpharoo Dec 05 '19 at 04:33
  • I already solve the problem. Should I post as answer because the problem is elsewhere? – Ahfa Dec 05 '19 at 07:03
  • I want to upvote but I cant upvote as a new contributor – Ahfa Dec 05 '19 at 07:20
0

UPDATE

Nothing wrong with the application, what you must do is:

ONLY USE PROVIDERS ONCE

Import the service to @ngmodule in app.module.ts, otherwise you will create instance each component / module.

Ahfa
  • 180
  • 8