1

I am new to Angular and I am using angular 7. I have a variable userEmail with the default value of "unknown" in a shared service pagedoctorService. After successful login, the variable updates with logged in Email. I have imported this service in other components but when accessing userEmail from other components, it shows the default value (unknown).

Here is what I done:

app.module.ts

...
import { PagedoctorService } from './services/pagedoctor.service';
...
...
providers: [PagedoctorService],
...

pagedoctor.service.ts

import { Injectable } from '@angular/core';
import { OktaAuthService } from '@okta/okta-angular';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Observable } from 'rxjs';

@Injectable({
  providedIn: 'root'
})
export class PagedoctorService {

  private accessToken;
  private headers;

  public userFullname: string= 'unknown';
  public userEmail: string= 'unknown';

  constructor(private oktaAuth: OktaAuthService, private http: HttpClient) {
    this.init();
  }

  async init() {
    this.accessToken = await this.oktaAuth.getAccessToken();
    this.headers = new HttpHeaders({
      Authorization: 'Bearer ' + this.accessToken
    });
  }
...

login.component.ts

import { Component, OnInit } from '@angular/core';
import { Router, NavigationStart} from '@angular/router';
import { PagedoctorService } from '../../services/pagedoctor.service';
...
constructor(private pdService: PagedoctorService){}
ngOnInit() {
...
//After successful login attempt using Okta
this.pdService.userEmail = res.user.profile.login; 
console.log(this.pdService.userEmail); //This shows that email is set correctly
this.signIn.loginRedirect('/urlform');
}

urlform.component.ts

import { Component, OnInit, Input } from '@angular/core';
import { PagedoctorService } from '../../services/pagedoctor.service';
...
...
constructor(private pdService: PagedoctorService) {
console.log(this.pdService.userEmail); // <== This shows *unknown*

Sounds like I am working with a fresh version of the service while I have provided it in module level. I am not really sure what I am missing here. Thanks in advance for your cooperation.

M Reza Saberi
  • 7,134
  • 9
  • 47
  • 76

3 Answers3

1

The best way to provide a service instance in the root injector and thus your whole application is:

import { Injectable } from '@angular/core';

@Injectable({
  providedIn: 'root',
})
export class PagedoctorService {
}

See: https://angular.io/guide/providers

An example here: https://stackblitz.com/edit/angular-fumwxh

Important

Try ceaping your constructor clean. Make only assigments no actions. Don't call any methods in a constructor. Could you please call the init method from outside and not internal from your constructor. Maybe the async method "init" is the problem.

But your code should work also. Maybe you can provide the code of your PagedoctorService.

UPDATE Ahh redirection. Ok that solves the issue! In your login.component you call: this.signIn.loginRedirect('/urlform').

When you redirect the SPA will be reloaded and the whole injector is created from scratch. That means that all your state is lost. You can avoid this using localstorage or sessionstorage for example!

import { Injectable } from '@angular/core';

@Injectable({
  providedIn: 'root',
})
export class PagedoctorService {
...
public get userFullname(): string {
    const res = localStorage.getItem('userFullname');
    return res == undefined ? 'unknown' : res;
  }
  public set userFullname(value: string) {
    localStorage.setItem('userFullname', value);
  }
}
...
Pierre
  • 794
  • 5
  • 15
1

I would be careful about putting public properties in services. The only public properties I usually add in services are subjects to manage state. If you want to pass the userEmail to other components, I would suggest either setting it in local storage, putting it a subject that is updated when you change it or as input from parent to child. For routing, you can also pass data from the login component to the navigated route through the route configurations. Please see link below:

How do I pass data to Angular routed components?

I hope this helps.

Paul
  • 460
  • 2
  • 7
0

try this in login.component

this.pdService.changeEmail(res.user.profile.login);

in PagedoctorService

` private emailOriginale = new BehaviorSubject('unknown');
     emailActtual = this.emailOriginale .asObservable(); 
     changeEmail(email: string) {
         this.emailOriginale.next(email)
     }`

end in urlform.component.ts

  this.pdService.emailActtual.subscribe(res => console.log(res));