0

I have this app.component.html:

<nav class="navbar navbar-expand-lg navbar-light bg-light">
  <div class='container'>
    <ul class="nav navbar-nav">
      <li class='nav-item'>
        <a class='nav-link' routerLink="/">Strona główna</a>
      </li>
      <li class='nav-item'>
        <a class='nav-link' routerLink="/about">O nas</a>
      </li>
      <li class='nav-item' *ngIf='!user'>
        <a class='nav-link' routerLink="/login">Zaloguj</a>
      </li>
      <li class='nav-item' *ngIf='!user'>
        <a class='nav-link' routerLink="/register">Zarejestruj</a>
      </li>
      <li class='nav-item' *ngIf='user'>
        <a class='nav-link' routerLink="/logout">Wyloguj</a>
      </li>
    </ul>
  </div>
</nav>
<main>
  <router-outlet></router-outlet>
</main>

What I'm trying to do is to show the /logout button if the user is logged in and hide it otherwise, and show the /login and /register buttons if the user is not logged in.

Here's my login logic:

import {Component} from '@angular/core';
import {AuthService} from '../core/auth.service';
import {Router, Params} from '@angular/router';
import {FormBuilder, FormGroup, Validators} from '@angular/forms';

@Component({
  selector: 'page-login',
  templateUrl: 'login.component.html',
  styleUrls: ['login.scss']
})

export class LoginComponent {
  loginForm: FormGroup;
  errorMessage: string = '';

  constructor(
    public authService: AuthService,
    private router: Router,
    private fb: FormBuilder
  ) {
    this.createForm();
  }

  createForm() {
    this.loginForm = this.fb.group({
      email: ['', Validators.required],
      password: ['', Validators.required]
    });
  }

  tryFacebookLogin() {
    this.authService.doFacebookLogin()
      .then(res => {
        this.router.navigate(['/user']);
      });
  }

  tryTwitterLogin() {
    this.authService.doTwitterLogin()
      .then(res => {
        this.router.navigate(['/user']);
      });
  }

  tryGoogleLogin() {
    this.authService.doGoogleLogin()
      .then(res => {
        this.router.navigate(['/user']);
      });
  }

  tryLogin(value) {
    this.authService.doLogin(value)
      .then(res => {
        this.router.navigate(['/user']);
      }, err => {
        console.log(err);
        this.errorMessage = err.message;
      });
  }
}

Example of the doLogin function:

doLogin(value){
  return new Promise<any>((resolve, reject) => {
    firebase.auth().signInWithEmailAndPassword(value.email, value.password)
    .then(res => {
      resolve(res);
    }, err => reject(err))
  })
}

I am new to Angular. I was mostly working with Express until now. I was thinking to set something like a session variable, to keep if the user is logged in, or not. How can I do it in Angular?

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
Alex Ironside
  • 4,658
  • 11
  • 59
  • 119
  • You can set a variable to localstorage when login is successfull and retreive it in any place in your application – JuanDM May 17 '18 at 12:56
  • Angular blog on login and logout nicely explain ed http://jasonwatmore.com/post/2016/09/29/angular-2-user-registration-and-login-example-tutorial – Rizwan May 17 '18 at 12:58

4 Answers4

3

Firebase offers an authentication object through the library. Store the result of the connection into a variable that you will be able to display.

import * as firebase from 'firebase/app';

randomFunction() {
  firebase.auth().onAuthStateChanged(user => {
    if(user) {
      this.logged = true;
    } else {
      this.logged = false;
    }
  });
}

In your HTML

<div *ngIf="logged; else #isAnonymous">
  <button>Log out</button>
</div>
<ng-template #isAnonymous>
  <button>Log in</button>
</ng-template>
  • And I should put this code in the `app.component.ts` file right? – Alex Ironside May 17 '18 at 13:07
  • you put it where you want to show/hide something depending on the user state. In your case, yes, I guess it's there, since it's the only HTML code you provided ! –  May 17 '18 at 13:09
  • Yes I forgot to add it in the question. I have a simple routing system, and I need this variable it to be available on every page. – Alex Ironside May 17 '18 at 13:15
  • Then make a shared service. You can learn what it is **[here](https://angular.io/guide/component-interaction#parent-and-children-communicate-via-a-service)** –  May 17 '18 at 13:16
2

Well as you asked in the comments of accepted answer you decided to use LocalStorage strategy to verify if user is logged in.

I suggest you create a service to manage all authentication stuff:

auth.service.ts

import { LocalStorageService } from 'angular-2-local-storage';

@Injectable()
export class AuthService {

  constructor(private http: Http, private localStorage: LocalStorageService) { }

 login(email: string, password: string): Observable<any>{
   //  Do Stuff  .....;
   //  if successfull set to LocalStorage
}

  isAuthenticated(): boolean{
    if (this.localStorage.get('isLoggedIn')){
      return true;
    }
    else{
      return false;
    }
  }

}

Now in any of your components you can inject that service and simply call in this way:

your.component.ts

@Component({
  selector: 'app-login',
  templateUrl: './login.component.html',
  styleUrls: ['./login.component.css']
})
export class LoginComponent implements OnInit {

  constructor(private authService: AuthService) { }
  let isLoggedIn = false;    


  ngOnInit() {

    isLoggedIn  = this.authService.isAuthenticated();

    if (isLoggedIn){
      alert('hello');
    }
  }

Now you can use the variable isLoggedIn in your template with the *ngIf

JuanDM
  • 1,250
  • 10
  • 24
  • 1
    That's exactly what I was looking for! Thank you – Alex Ironside May 21 '18 at 09:20
  • What if the element you want to hide is on the main component and sigIn is in another component? This solution won't work! – Bilal Ahmed Yaseen Dec 20 '18 at 08:59
  • I cant understand your comment, see `authService` as a helper to validate if the user is authenticated, you can inject this service wherever you need and call the `isAuthenticated` method, can you explain better your point? – JuanDM Dec 20 '18 at 12:40
1

Just set a variable isLoggedIn in your component level (or LocalStorage to access it in the whole application). Once the user is successfully authenticated, you can set it to true/false.

Use *ngIf on the component level to display whatever information based on Login

JuanDM
  • 1,250
  • 10
  • 24
Sajeetharan
  • 216,225
  • 63
  • 350
  • 396
  • So if I create a variable in `app.component.ts` can I change it in `auth.service.ts`? A completely different place. Or do I have to use localStorage? – Alex Ironside May 17 '18 at 13:01
  • LocalStorage is the way to go because the variable cant be used in the service because they are in diferent contexts – JuanDM May 17 '18 at 13:03
  • If you are trying to access variables in different components you would need to create a `service` that allows each to transfer data between each other. Or you can use local storage. Check out https://angularfirebase.com/lessons/sharing-data-between-angular-components-four-methods/ – Vincent Nguyen May 17 '18 at 13:03
  • @JuanDM Ok I got the localstorage to work, but how can I compare the localstorage variable in `*ngIf`? – Alex Ironside May 17 '18 at 13:52
  • I posted as an answer – JuanDM May 17 '18 at 14:06
1

In your component, you can have a variable that holds user's login status. So along with navigating to the /user route you would also want to do this.isAuthenticated= true as given below.

When do logout make sure that you set this false.

this.isAuthenticated = false;

This may be the sample component code:

import {Component} from '@angular/core';
import {AuthService} from '../core/auth.service';
import {Router, Params} from '@angular/router';
import {FormBuilder, FormGroup, Validators} from '@angular/forms';

@Component({
  selector: 'page-login',
  templateUrl: 'login.component.html',
  styleUrls: ['login.scss']
})

export class LoginComponent {
  isAuthenticated:boolean = false;
  loginForm: FormGroup;
  errorMessage: string = '';

  constructor(
    public authService: AuthService,
    private router: Router,
    private fb: FormBuilder
  ) {
    this.createForm();
  }

  createForm() {
    this.loginForm = this.fb.group({
      email: ['', Validators.required],
      password: ['', Validators.required]
    });
  }

  tryFacebookLogin() {
    this.authService.doFacebookLogin()
      .then(res => {
        this.isAuthenticated = true;
        this.router.navigate(['/user']);
      });
  }

  tryTwitterLogin() {
    this.authService.doTwitterLogin()
      .then(res => {
      this.isAuthenticated = true;
        this.router.navigate(['/user']);
      });
  }

  tryGoogleLogin() {
    this.authService.doGoogleLogin()
      .then(res => {
      this.isAuthenticated = true;
        this.router.navigate(['/user']);
      });
  }

  tryLogin(value) {
    this.authService.doLogin(value)
      .then(res => {
        this.isAuthenticated = true;
        this.router.navigate(['/user']);
      }, err => {
        this.isAuthenticated = false;
        console.log(err);
        this.errorMessage = err.message;
      });
  }

  logOut(){
    //write logout from server here
    this.isAuthenticated = false;
  }
}

Then on your template you will do

<div *ngIf="isAuthenticated>Show Logout button</div>
<div *ngIf="!isAuthenticated">Show Login button</div>
Sudhakar
  • 3,104
  • 2
  • 27
  • 36
Vincent Nguyen
  • 1,555
  • 4
  • 18
  • 33