Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular2, call service function, Cannot read property '***' of undefined

I am calling a function from a service, but I always get Cannot read property 'getCurrentUser' of undefined.

This is my service, authentication.service.ts

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

@Injectable()
export class AuthenticationService {
  public token: string;
  private url = 'http://192.168.201.211:8024/api-token-auth/';
  private options: RequestOptions;
  private currentUser: any;

  constructor(private http: Http) {
    // set token if saved in local storage
    this.currentUser = JSON.parse(localStorage.getItem('currentUser'));
    this.token = this.currentUser && this.currentUser.token;
    let headers = new Headers({ 'Content-Type': 'application/json' });
    this.options = new RequestOptions({ headers: headers });
   }

  login(username: string, password: string): Observable<boolean> {
    return this.http.post(this.url, JSON.stringify({ username: username, password: password }), this.options)
        .map((response: Response) => {
            // login successful if there's a jwt token in the response
            let token = response.json() && response.json().token;
            if (token) {
                // set token property
                this.token = token;

                // store username and jwt token in local storage to keep user logged in between page refreshes
                localStorage.setItem('currentUser', JSON.stringify({ username: username, token: token }));

                // return true to indicate successful login
                return true;
            } else {
                // return false to indicate failed login
                return false;
            }
        });
  }

  logout(): void {
    // clear token remove user from local storage to log user out
    this.token = null;
    localStorage.removeItem('currentUser');
  }

  getCurrentUser(): Observable<any> {
    console.log('i am in getCurrentUser');
    this.currentUser = JSON.parse(localStorage.getItem('currentUser'));
    return this.currentUser;
  }
}

Then, I call getCurrentUser from another component user-detail.component.ts:

import { Component, OnInit, Input } from '@angular/core';

import 'rxjs/add/operator/switchMap';
import { User } from '../user';
import { AuthenticationService } from '../authentication.service';

@Component({
  selector: 'app-user-detail',
  templateUrl: './user-detail.component.html',
  styleUrls: ['./user-detail.component.css']
})

export class UserDetailComponent implements OnInit {
  @Input() user: User;  // current page belonger
  loginUser: any;  // current login user
  canEdit: boolean = false;
  constructor(
    private authService: AuthenticationService,
  ) {
   }

  ngOnInit() {

    // always watch out login user
    setInterval(this.checkUserMatch, 5000);
  }


  //  check if current login user can edit this page
  checkUserMatch() {
    this.loginUser = this.authService.getCurrentUser();
    if (this.loginUser) {
      if (this.user.username === this.loginUser.username) {
        this.canEdit = true;
      }
      else {
        this.canEdit = false;
      }
    }
    else {
      this.canEdit = false;
    }
    console.log(this.canEdit);
  }
}
like image 590
Belter Avatar asked Dec 23 '22 14:12

Belter


1 Answers

The context of this changes inside checkUserMatch when you pass a reference to setInterval like this setInterval(this.checkUserMatch, 5000);.

Use arrow function to wrap the function. This will set the correct this inside checkUserMatch``:

setInterval(() => this.checkUserMatch(), 5000);

Or use Function.bind:

setInterval(this.checkUserMatch.bind(this), 5000);

See red flags for this.

like image 164
Saravana Avatar answered Dec 28 '22 09:12

Saravana