1

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

7
  • 1
    Make sure you have UserService in providers array inside module. Commented Dec 4, 2018 at 21:52
  • Alternative to what @Oen44 said, change @Injectable() to @Injectable({ providedIn: 'root' }) on top of your service. It's the preferred way in recent Angular versions to have your service injectable everywhere (as a singleton). Commented Dec 4, 2018 at 21:59
  • @Oen44 yup, UserService is in my app.module.ts Commented Dec 4, 2018 at 22:00
  • @Jeto thanks for the advice, ill be doing that from now on, unfortunately I am still getting undefined Commented Dec 4, 2018 at 22:04
  • @Matt Could you try and make a (minimal) StackBlitz reproducing the issue? Commented Dec 4, 2018 at 22:09

2 Answers 2

2

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.

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

Comments

1

I thought when you declare like this

@Injectable({providedIn:'root'})

it is available to the entire application

1 Comment

No it's not, it is available only in the module scope,

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.