0
votes

I am new to Angular and having hard time grasping how to deal with async requests.

I have 3 components: parent - AppComponent children - LoginComponent,NavbarComponent,DashboardComponent,MainComponent,SidebarComponent

and one AuthService

On pressing "Login" button at the logging component I need to transfer boolean "true" value to all components. On pressing "Logout" button at the navbar component I need to transfer boolean "false" value to all components and set user=null

if true ->

  1. set token in localStorage with user ID

  2. preform http.get("http://localhost:3000/user/"+id) request to retrieve full user info and inject user info to Dashboard,Main,Sidebar,App and Navbar components.

The problem is that whenever I logout the false/true value updates on all components immediately but the user info does not turn into null unless I refresh the page or send it with router to another component and then return to MainComponent, same thing with new login.

How do I update both user info and status in all components immediately without refreshing the page?

authService:

import { Injectable } from "@angular/core";
import { HttpClient } from "@angular/common/http";
import { Router } from "@angular/router";

import { User } from "../models/User";

@Injectable({ providedIn: "root" })
export class AuthService {
  user: User;
  private _url = "http://localhost:5000/user/";

  constructor(private http: HttpClient, private _router: Router) {}

  registerUser(user) {
    return this.http.post<any>(this._url + "register", user);
  }

  loginUser(user) {
    return this.http.post<any>(this._url + "login", user);
  }

  logoutUser() {
    localStorage.clear();
    this._router.navigate(["/"]);
  }

  loggedIn() {
    return !!localStorage.getItem("token");
  }

  getToken() {
    return localStorage.getItem("token");
  }

  getCurrentUser() {
    return this.http.get<any>("http://localhost:5000/shop/current");
  }
}

Main/Sidebar component:

import { Component, OnInit, DoCheck } from "@angular/core";

import { AuthService } from "src/app/services/auth.service";

import { User } from "src/app/models/User";

@Component({
  selector: "app-sidebar",
  templateUrl: "./sidebar.component.html",
  styleUrls: ["./sidebar.component.css"]
})
export class SidebarComponent implements OnInit, DoCheck {
  isSidenavOpen: boolean = true;
  user: User;

  constructor(private _authService: AuthService) {}

  ngOnInit() {
    if (this._authService.loggedIn()) this._authService.getCurrentUser().subscribe(res => (this.user = res.user));
    else this.user = null;
  }

  ngDoCheck() {
    if (!this._authService.loggedIn()) this.user = null;
  }
}

login:

  constructor(private _authService: AuthService, private _router: Router) {}



  // onLoginUser() {
  //   this._authService.loginUser(this.loginUserData).subscribe(
  //     res => {
  //       localStorage.setItem("token", res.token);
  //       localStorage.setItem("user", res.user._id);
  //       this._router.navigate(["/"]);
  //     },
  //     err => console.log(err)
  //   );
  // }
}
1
where is your user info created? - Vadi
I updated the question with the code. New user is created on register component - Karina

1 Answers

0
votes

Use event EventEmitter to emit event on login, logout etc and listen in each component, that depends on user data.

In service, where you call logoutUser, loginUser methods of AuthService:

// LoginService
userLoggin: EventEmitter<User> = new EventEmitter();
userLoggout: EventEmitter<any> = new EventEmitter();

constructor(private _authService: AuthService, private _router: 
Router) {}

loginUser() {
  this._authService.loginUser(this.loginUserData).subscribe(
    res => {
      localStorage.setItem("token", res.token);
      localStorage.setItem("user", res.user._id);
      this.userLoggin.emit(res.user);
      this._router.navigate(["/"]);
    },
    err => console.log(err)
    );
  }

  logoutUser() {
  this._authService.logoutUser().subscribe(
    res => {
      this.userLoggout.emit();
    },
    err => console.log(err)
    );
  }
}

Then in component:

import { Component, OnInit, DoCheck } from "@angular/core";

import { AuthService } from "src/app/services/auth.service";

import { User } from "src/app/models/User";

import { LoginService } from "src/app/services/login.service";

@Component({
  selector: "app-sidebar",
  templateUrl: "./sidebar.component.html",
  styleUrls: ["./sidebar.component.css"]
})
export class SidebarComponent implements OnInit, DoCheck {
isSidenavOpen: boolean = true;
user: User;
loggin$: Subscription;
logout$: Subscription;

  constructor(private _authService: AuthService, private _loginService: LoginService) {
    this.loggin$ = this._loginService.userLoggin.subscribe(user => {
      this.user = user;
    });

    this.logout$ = this._loginService.userLoggout.subscribe(user => {
      this.user = null;
    });
  }

  ngOnInit() {
  }

  ngOnDestroy() {
    this.loggin$.unsubscribe();
    this.logout$.unsubscribe();
  }
}