1

I have a strange situation. I have nav component which I want to show only when the user is logged in. I am trying to manage that using a variable which is false by default and when a user logs in, the value is true and menu is visible.

the current situation is that, when a user clicks on the logout link on the MenuComponent, the event is emitted and the value changes. But on login, after the http response, it is not getting triggered.

Here is the menu component:

import { Component, OnInit } from '@angular/core';
import { UserService } from './../user/user.service';
import { Router } from '@angular/router';

@Component({
  moduleId: module.id,
  selector: 'app-navigation',
  templateUrl: 'navigation.component.html',
  styleUrls: ['navigation.component.css'],
  providers: [UserService]
})
export class NavigationComponent implements OnInit {
  public menuStatus;
  constructor(private userService: UserService, private router: Router) {
    this.menuStatus = userService.isLoggedIn();
  }
  ngOnInit() {
    this.userService.userLoggedOut$.subscribe(data => {
      console.log('userLoggedOut subscribe');
      this.menuStatus = data;
    });

    this.userService.userLoggedIn$.subscribe(data => {
      console.log('userLoggedIn subscribe');
      this.menuStatus = data;
    });
  }
  logout() {
    this.userService.userLogout();
    this.router.navigate(['/login']);
  }
}

In this, the logout button click triggers logout function. The user service userLogout function has the event emitter. Here is the event emitter:

import {Injectable} from '@angular/core';
import { Headers, Http } from '@angular/http';
import 'rxjs/add/operator/toPromise';
import { Subject } from 'rxjs/Subject';
import { Config } from './../shared/config';

@Injectable()
export class UserService {
  private loggedIn;
  private userLoginUpURL;
  private userLoggedInEvent = new Subject();
  private userLoggedOutEvent = new Subject();

  userLoggedIn$ = this.userLoggedInEvent.asObservable();
  userLoggedOut$ = this.userLoggedOutEvent.asObservable();

  constructor(private http: Http, private config: Config) {
    this.loggedIn = false;
    this.loggedIn = !!localStorage.getItem('access_token');
    this.userLoginUpURL = this.config.loginUrl;
  }

  getUserObject() {
    return JSON.parse(localStorage.getItem('user_object'));
  }

  userLogin(userLoginDetails) {
    let headers = new Headers({
      'Content-Type': 'application/json'
    });

    let postData = {
      email: userLoginDetails.email,
      password: userLoginDetails.password
    };

    return this.http
      .post(this.userLoginUpURL, JSON.stringify(postData), {headers: headers})
      .toPromise()
      .then(res => {
        localStorage.setItem('access_token', res.json().access_token.access_token);
        localStorage.setItem('user_object', JSON.stringify(res.json().user));
        this.loggedIn = true;
        this.userLoggedInEvent.next(this.loggedIn);
        return res.json();
      })
      .catch(this.handleError);
  }

  userLogout() {
    // destroy the local storage variabled
    localStorage.removeItem('access_token');
    localStorage.removeItem('user_object');

    // setup the login status to false
    this.loggedIn = false;
    this.userLoggedOutEvent.next(false);
  }

  isLoggedIn() {
    return this.loggedIn;
  }

  private handleError(error: any) {
    return Promise.reject(error.message || error);
  }
}

Problem is, after logging in when I am calling this.userLoggedInEvent.next(this.loggedIn), the event doesn't fire.

Can someone please help. There is any easy fix where I can refresh the window and redirect the user to the Dashboard, but I don't want to refresh the page and do it the correct way. Please help.

2
  • Where do you call userLogin() from? Commented Jun 26, 2016 at 16:29
  • userLogin() is called through a function inside the LoginComponent which has a login function. Do you think that code will also help? Let me know and I will add that if required. Commented Jun 26, 2016 at 16:43

1 Answer 1

1

Ensure you provide UserService only once on a common parent (root component) otherwise different components will get different instances and listening on one instance while emitting on another won't achieve much ;-)

Sign up to request clarification or add additional context in comments.

7 Comments

Well, if I add the user service inside my main.ts component and then inside my menu component if I call that through constructor... is that OK?
Not sure what you mean by "add". If you want to share an instance, you must not add it to providers of both components.
Can you tell me how to do it
Do what? . . . . .
Hey, Gunter Zochbauer... thanks for the tip.. yes it worked perfectly. I was calling the user service in LoginComponent and inside MenuComponent as well. I think that was the culprit. I removed it as a provider from both MenuComponent and LoginComponent and loaded it inside main.ts and it worked. Thanks a ton.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.