Search code examples
angulartypescriptservicenativescriptangular7

Angular 7 service file not keeping variable state


I have 2 components and 1 service file, There is a login component and a dashboard component.

This is my login component, it subscribes to a http request in the service file. When I console log this.userService.user it returns correctly. When I route to dashboard and log the this.userService.user inside the dashboard component its undefined.

import { Component, OnInit } from "@angular/core";
import { RouterExtensions } from "nativescript-angular/router";
import { UserService } from "../../shared/services.module";

@Component({
    selector: "login",
    moduleId: module.id,
    templateUrl: "./login.component.html",
    styleUrls: ["./login.css"],
})
export class LoginComponent implements OnInit {
    email: string;
    password: string;

    constructor(private router: RouterExtensions, private userService: UserService) { }

    signUp() {
      this.userService.login(this.email, this.password)
      .subscribe(res => {
          console.log(this.userService.user)
          this.router.navigate(["/dashboard"], { clearHistory: true, animated: false });
      });
    }

    ngOnInit(): void {
    }
}

This is my dashboard component, when I log this.userService.user its undefined.

import { Component, OnInit, Input } from "@angular/core";
import { RouterExtensions } from "nativescript-angular/router";
import { UserService } from "../../shared/services.module";

@Component({
    selector: "dashboard",
    moduleId: module.id,
    templateUrl: "./dashboard.component.html",
    styleUrls: ["./dashboard.css"],
})
export class DashboardComponent implements OnInit {
    constructor(private router: RouterExtensions, private userService: UserService) {
   }

    ngOnInit(): void {
      console.log(this.userService.user)
      console.log(this.userService.getUserName())
    }
}

this is my service file

import { Injectable } from "@angular/core";
import { HttpClient } from '@angular/common/http';
import { HttpHeaders } from '@angular/common/http';
import { Config } from "../config";
import { catchError } from 'rxjs/operators';
import { map, delay, retryWhen, take } from 'rxjs/operators';
import { HttpErrorHandler, HandleError } from '../../http-error-handler.service';
import { User } from '../../models/user/user'

const httpOptions = {
  headers: new HttpHeaders({
    'Content-Type':  'application/json',
  })
};
@Injectable()
export class UserService {
  user: any;
  private handleError: HandleError;

  constructor(private http: HttpClient, httpErrorHandler: HttpErrorHandler) {
    this.handleError = httpErrorHandler.createHandleError('HeroesService');
  }

  getUserName() {
    console.log("return name");
    console.log(this.user)
    if (!this.user) {
      return "failed";
    }
    console.log(this.user.name)
    return this.user.name
  }

  login(email, password) {
    let data = JSON.stringify({'email': email,'password': password})
    return this.http.post(Config.userUrl + 'login', data, httpOptions)
    .map((res: any) => {
      let u = res.user
      this.user = new User(u.name, u.email)
      console.log(this.user)
      return res
    })
    .pipe(
      catchError(this.handleError('login', null))
    );
  }
}

It's strange that when I even use a helper function like getUserName to just return the name its still undefined even in the service file.

Any idea why it's returning undefined? Any help would be greatly appreciated. Thanks


Solution

  • Try this:

    Module where are you providing the service

    @NgModule({
        imports: [
            ...
        ],
        declarations: [
            ...
        ],
        providers: [
            ... // You have propably there the service that you want to provide globally, remove it
        ]
    })
    export class YourModule {
        static forRoot(): ModuleWithProviders {
            return {
                ngModule: YourModule, // name of this module
                providers: [ YourService ] // put there the service, that you want to provide globally
            };
        }
    }
    

    app.module.ts

    @NgModule({
        declarations: [
            AppComponent,
            ...
        ],
        imports: [
            ...
            YourModule.forRoot() // add this
        ],
        providers: [
            ...
        ],
        bootstrap: [ 
            AppComponent 
        ]
    })
    export class AppModule {
    }
    

    Service that you want to provide globally

    @Injectable() // remove the "providedIn: ..." if you have it there
    export class YourService {
        ...
    }
    

    Components

    @Component({
        selector: "dashboard",
        moduleId: module.id, // remove this line
        templateUrl: "./dashboard.component.html",
        styleUrls: ["./dashboard.css"],
    })
    export class DashboardComponent implements OnInit {
         ...
    }
    

    And dont forget to importYourModule into the imports of the module where you want to use YourService.