-1

I just want to display the email of this logged in user in the header

Here is my AuthService:

import { Injectable } from '@angular/core';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
import { User } from '../interfaces/user';

export interface Form {
  email: string;
  password: string;
}

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

  constructor(private http: HttpClient) { }

  login(login): Observable<boolean> {
    return this.http.post<{ token: string }>(
      'https://megaphone-test.herokuapp.com/api/auth/login',
      login)
      .pipe(
        map(result => {
          localStorage.setItem('access_token', result.token);
          return true;
        })
      );
  }

  getUser(): Observable<User> {
    const token = localStorage.getItem('access_token');
    return this.http.get<User>(
      'https://megaphone-test.herokuapp.com/api/user',
      {
        headers: new HttpHeaders().append('x-access-token', token)
      });
  }

  isAdmin() {
    const token = localStorage.getItem('access_token');
    return this.http.get<User[]>(
      'https://megaphone-test.herokuapp.com/api/user/isAdmin',
      {
        headers: new HttpHeaders().set('x-access-token', token)
      }
    )
      .subscribe(
        res => console.log(res['isAdmin']),
        err => console.log(err)
      );
  }

  logout() {
    localStorage.removeItem('access_token');
  }

  public get loggedIn(): boolean {
    return (localStorage.getItem('access_token') !== null);
  }

}

Here is my Component:

import { Component, OnInit, Input } from '@angular/core';
import { AuthService } from '../../core/services/auth.service';
import { Router } from '@angular/router';
import { Observable } from 'rxjs';
import { User } from '../../core/interfaces/user';

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

  user: User;

  constructor(public auth: AuthService, private router: Router) { }

  ngOnInit() {
    this.auth.getUser()
    .subscribe(
      user => this.user = user
    );
  }

  doLogout() {
    this.auth.logout();
    this.router.navigate(['login']);
  }

}

Here is my Template:

 <div class="header-actions" *ngIf="auth.loggedIn">
        <clr-dropdown>
            <button class="nav-text" clrDropdownTrigger>
                    {{ user.email }}
                <clr-icon shape="caret down"></clr-icon>
            </button>
            <clr-dropdown-menu *clrIfOpen clrPosition="bottom-right"> 
                <a href="..." clrDropdownItem>Preferences</a>
                <a clrDropdownItem (click)="doLogout()">Log out</a>
            </clr-dropdown-menu>
        </clr-dropdown>
    </div>

ERROR HeaderComponent.html:17 ERROR TypeError: Cannot read property 'email' of undefined

It seems no matter which way I code this it still never knows who the user is. I can console log it all day and it shows this logged in user no problems.

Cheers,

Gonçalo Peres
  • 11,752
  • 3
  • 54
  • 83
Clayton Allen
  • 239
  • 3
  • 15
  • I remember debugging via console.log, and though it was displaying my data fine, my program was saying it doesn't exist. I believe console.log does something along the async pipe, and can fool you into thinking that data was available. – Bytech Nov 12 '18 at 22:32
  • It is `user` that does not exist yet when the view is shown initially. Did you try `{{user?.email}}`? – ConnorsFan Nov 12 '18 at 22:32
  • yup just now. The problem is my "user" email is not a nullable property – Clayton Allen Nov 12 '18 at 22:35
  • `?.` is the Angular [safe navigation operator](https://angular.io/guide/template-syntax#the-safe-navigation-operator----and-null-property-paths); it is not about a nullable property. What do you get with it? Do you still have an error? – ConnorsFan Nov 12 '18 at 22:36
  • @ConnorsFan is right. When the component is initialized, user will be null. Doing `user?.email` will solve your problem. – Boland Nov 12 '18 at 22:39
  • I like testing with `*ngIf` better (avoids random empty elements). But this definitely looks like the same issue as the referenced question. – Jeto Nov 12 '18 at 22:43
  • You're right. Using "?." does take the error away from the console. However, does not solve the missing email from the header component. – Clayton Allen Nov 12 '18 at 22:58
  • Because your user is not logged in? Where are you calling the `login` method from your service? – Jeto Nov 12 '18 at 23:01
  • Login happens a step before this error. I logged in and get a token just fine. Then I call get user in the auth service which is fine because it returns the user. and I log the user just fine in the console. so on nginit i am trying to set the user – Clayton Allen Nov 12 '18 at 23:12
  • Please show where you put your `console.log(this.user)` and what it shows. No reason that `{{user?.email}}` wouldn't display anything if it's filled in. – Jeto Nov 12 '18 at 23:59

2 Answers2

0
 ngOnInit() {
    this.auth.getUser()
    .subscribe(
      user => this.user = user['user']
    );
  }

On the component init

Clayton Allen
  • 239
  • 3
  • 15
  • 1
    If you had to do that, it means you had a wrong type generic on that .get() method. Change it to this.http.get<{user: User}> and next time pay extra attention to how the data comes back from the backend. – itsundefined Nov 12 '18 at 23:26
0
 getUser(): Observable<User> {
    const token = localStorage.getItem('access_token');
    return this.http.get<User>(
      'https://megaphone-test.herokuapp.com/api/user',
      {
        headers: new HttpHeaders().append('x-access-token', token)
      }
    );
  }
Clayton Allen
  • 239
  • 3
  • 15