-3

The service's only purpose is to keep track of if the user is still logged in or not. (I'm in version 8 of angular)

@Injectable({
   providedIn: 'root',
})
export class LoginStatusService {
  subject: any;

  initialCreate() {
    this.subject = new Subject();
    this.subject.next(false);
  }
}

I have two different navbars (navbar, navresearch). navresearch has a button to send the user back to the main navbar page. The navbar content depends on whether the user is logged in or not.

app.module does not have this service in providers:

  ],
   providers: [
      AuthService,
      ErrorInterceptorProvider
   ],
   bootstrap: [
      AppComponent

As you can see it starts in AppComponent where I thought I could initialize the RxJs Subject by calling the function shown above - see here:

export class AppComponent {
  title = 'Hunter';

  constructor(private LoggedIn: LoginStatusService) {
    this.LoggedIn.initialCreate();   **<--**
  }
}

Switching pages back to the navbar (main) page causes app.component to be initialized again and thus the RxJs subject gets reinitialized - and I lose user login status.

What am I missing?

Wilt
  • 41,477
  • 12
  • 152
  • 203
Yogi Bear
  • 943
  • 2
  • 16
  • 32
  • 1. How do you differentiate if a different user logs in? 2. Why exactly do you use a Subject here? (IMO, it isn't required) – Nicholas K Apr 16 '20 at 16:38
  • 1
    Why doesn't that initial creation happen in the *service's* constructor? – jonrsharpe Apr 16 '20 at 16:38
  • I did try to initialize in the service's constructor, but when I go back to the main page, it gets loaded again and reinitialized (?? can't see why) ... BUT After the main page leaves to the navResearch page, the loginStatus remains correct .. thus the service didn't get reinitialized. – Yogi Bear Apr 16 '20 at 16:42
  • Put a constructor in the service with a console log.. it should only show once. If not, there is something wrong with you providers somewhere, OR you have a hard reload of the app itself somehow. – MikeOne Apr 16 '20 at 17:12
  • Thanks MikeOne. I'm working on a model. I'll update this when I figure it out. – Yogi Bear Apr 16 '20 at 17:21

2 Answers2

2

Please don't depend on the Angular services alone to maintain the user session details, as when the user reloads the application angular services will loose the state.

Please save the user logged in data to the localStorage or sessionStorage based on the requirement.

Thanks

  • Thanks guys.. I tried Observables (BehaviorSubject) and I found things were still broken. However, I found some things that were causing trouble, but the idea of using local or session storage really appealed to me. Thanks both. :-) – Yogi Bear Apr 17 '20 at 21:23
  • This is not answering the question about how to keep a state inside a service. Using a service is justified and that something needs to be provided to the service and stored somewhere else is obvious. – Wilt Apr 18 '20 at 07:27
0

If you want to use a Subject, you probably want to use a BehaviorSubject so that late subscribers also get the correct login status. I also recommend like many others did in the comments to initialize the subject in the service constructor method. It is not the responsibility of a single component to initialize the service. Like you noticed components get destroyed and reinitialized but also your application could load another component first, then the Service will never be initialized and when you later use it it will not return any result.

You should also rather not expose your subject outside the service, it would be better to make it private and return it from some public method as an observable.

Another advantage of using a BehaviorSubject in this case is that you can also simply get the value directly (not as an observable) which can be practical for one time user cases where you need the current status on the fly. Here an example on what your service could look like. I don't know where you get the initial status from (local storage, session, cookie) so I created some imaginary dependency.

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

  private loggedIn: BehaviorSubject<boolean>;

  constructor(dependencyProvidingLoginStatus: LoginStatusProvider) {
    this.initalize();
  }

  initialize() {
    const loggedIn = this.dependencyProvidingLoginStatus.isLoggedIn();
    this.loggedIn = new BehaviorSubject(loggedIn);
  }

  public getLoginStatus(): boolean {
    this.loggedIn.getValue();
  }

  public getLoginStatusObservable(): Observable<boolean> {
    this.subject.asObservable();
  }

  // should maybe not be public? Try to solve this inside your service?
  public changeStatus(value: boolean) {
    this.loggedIn.next(value);
  }

}
Wilt
  • 41,477
  • 12
  • 152
  • 203
  • Thanks guys.. I tried Observables (BehaviorSubject) and I found things were still broken. However, I found some things that were causing trouble, but the idea of using local or session storage really appealed to me. Thanks both. :-) – Yogi Bear Apr 17 '20 at 21:22
  • @YogiBear Yes, you need to store it somewhere, but you should also think that what you have stored in localstorage (ie a token) can expire and then you need to validate it before using it. That is where your service comes in... – Wilt Apr 18 '20 at 07:22