Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular2 observables - subscribe doesn't update my variable when user logs in

So I am trying to update my menu when a user logs in. I have read several answers about similar problems, but I still can't get it to work.

nav-bar.component.html:

<li *ngIf="isLoggedIn"><a routerLink="/" (click)="logout($event);"> {{ logoutLabel }}</a></li>
<li *ngIf="!isLoggedIn"><a routerLink="/login (click)="showPopup($event);">{{ loginLabel }}</a></li>

In nav-bar.component.ts I open a modal with the login-form and also look for changes in a variable from login.service

import { SuPopupLoginComponent } from '../shared/su-popup-login/su-popup-login.component';
import { LoginService } from '../login/login.service';
...imports...

@Component({
   selector: 'app-nav-bar',
   templateUrl: './nav-bar.component.html',
   styleUrls: ['./nav-bar.component.scss']
})
export class NavBarComponent implements OnInit {
  loginLabel: string;
  public isLoggedIn: boolean;

   constructor(private loginService: LoginService, private suPopupLoginComponent: SuPopupLoginComponent) {
      loginService.getIsLoggedIn.subscribe((bool: boolean) => {
         this.isLoggedIn = bool;
         console.log('NavBarComponent', this.isLoggedIn);
      });
   }

   showPopup(event) {
      event.preventDefault();
      this.suPopupLoginComponent.showPopup();

      If I call login here It works just as expected

      // this.loginService.login('[email protected]', 'Test123')
      //      .subscribe(
      //        data => {
      //          if (data) { // If login was successful data is true.
      //            let redirect = 'license-overview';
      //            this.router.navigate([redirect]);

      //          } 
      //        }
      //      );
  }  

   logout(event) {
      event.preventDefault();
      this.loginService.logout();
   }
   ngOnInit() { }
}

su-popup-login.component.ts - login-form and call to login function:

import { LoginService } from '../../login/login.service';
import { Injector } from '@angular/core';

@Component({
  selector: 'su-popup-login',
  templateUrl: './su-popup-login.component.html',
  styleUrls: ['./su-popup-login.component.scss'],
  providers: [LoginService]
})

export class SuPopupLoginComponent implements OnInit {

   constructor(private loginService: LoginService, private injector: Injector) { }

   public showPopup() {
     Css and showing modal
   }

   login(event, mail, password) {
      this.loginService.login(mail, password)
         .subscribe(
            data => {

              if (data) { // If login was successful data is true.

              // Navigate to view after login success.
              this.router = this.injector.get(Router);
              let redirect = 'license-overview';
              this.router.navigate([redirect]);

        }
      }
    );
   }

login.service.ts

import { Injectable } from '@angular/core';
import { Http, Headers, Response } from '@angular/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/map';
import { BehaviorSubject } from 'rxjs/BehaviorSubject';

@Injectable()
export class LoginService {
   private isLoggedInSource = new BehaviorSubject<boolean>(localStorage.getItem('currentUser') ? true : false);
   public _isLoggedIn: Observable<boolean> = this.isLoggedInSource.asObservable();

   constructor(private http: Http) { }

   private isLoggedIn(logged: boolean) {
      this.isLoggedInSource.next(logged);
   }

   get getIsLoggedIn() {
      return this._isLoggedIn;
   }

   login = (mail: string, password: string): Observable<boolean> => {
   let loginUrl = '/api/authenticate';
   let body = JSON.stringify({ mail, password });

   return this.http.post(loginUrl, body)
      .map((response: Response) => {
          let user = response.json();

          if (user && user.tokenId) {
            this.isLoggedIn(true);

            // Add to local storage
           localStorage.setItem('currentUser', JSON.stringify({ mail: mail, tokenId: user.tokenId }));
           return true;  // Login success
         }
         else {
           return false; // Login failed
         }
      });
   }
}

It works fine if I call this.loginService.login('user', 'pass') from nav-bar.component, but not when login is called from su-popup-login.component.ts. Also, the this.loginService.logout() from nav-bar.component.ts works fine.

Does the subscribe call have to be in the same component as the calls to login/logout? If so, I guess I just don't understand how Observables work.

Thankful for any help or comments.

like image 890
bagling Avatar asked May 31 '26 21:05

bagling


1 Answers

providers: [LoginService] in su-popup-login.component.ts created different instance of LoginService.

To make it work, you have to make sure that both components share single instance of LoginService

To avoid that use providers: [LoginService] in your ngModule of appcomponent or coremodule and remove providers: [LoginService] from su-popup-login.component.ts

like image 89
Nikhil Shah Avatar answered Jun 03 '26 11:06

Nikhil Shah



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!