Mujahid
Mujahid

Reputation: 1237

Angular 2 service get returns undefined

In my current project, I have a very simple service which sets a string when a request comes from first page and show it in the second page using the same service. Setting the text is working perfectly. But when I called the get function, it returns undefined.

This is my service

import { Injectable } from '@angular/core';

@Injectable()
export class TsService {

  constructor() { }

  ts: string;

  getTs() : string {
      return this.ts;
  }

  setTs(ts) : void {
      this.ts = ts;
  }

}

In my first component I imported the Service

import { TsService } from './ts.service';

and added it to the providers

providers: [TsService]

and initialized in the contructor

private tsService: TsService

and to the button click, I set a string as well

this.tService.setTs(form.value.member)

In my second component, followed the same steps mentioned above except in the constructor I assigned as follows

this.ts = tsService.getTs();

but it gives me undefined. Is there anything that I missed

Upvotes: 1

Views: 2443

Answers (3)

Manish
Manish

Reputation: 5056

As i can make out from your code. You have registered your service as a provider in your component. like

providers: [TsService]

What this line of code will do. Is that it will fetch a new Instance of your service as soon as your component comes into play. So from first component lets say ComponentA you set the service variable as

this.tService.setTs(form.value.member)

But here ComponentA is having suppose Instnace1 of the service. So you have set the value to Instance1 of the Service. Now you navigate to second component say ComponentB As soon as ComponentB comes into play it angular creates a new Instance of the service and same is made available to ComponentB. Now there are two Instances of your service one with ComponentA and one with ComponentB. but you have set the variable using ComponentA so it wont be available to ComponentB hence

this.ts = this.tsService.getTs();

this returns undefined.

In order to check whether you variable is set or not you can try

this.tService.setTs(form.value.member);
console.log(this.tsService.getTs());

in your ComponentA it will log the value set.

The solution for this problem of your is to share the same Instance and that can be achieved by registering the service as provider in the AppModule.

As official docs say

On the one hand, a provider in an NgModule is registered in the root injector. That means that every provider registered within an NgModule will be accessible in the entire application.

For more please refer :-

Dependency Injection

NgModule Injectors

Hope it helps :)

Upvotes: 1

Randika Perera
Randika Perera

Reputation: 65

You may have use two instances of data object. use one data service for set and get data.Then you can access to same data object within different components.

And if you set that service as a provider for your components individually those gonna work as different instances. If you need only one instance for your whole app you can set that service as a provider in app.module.ts file.

Upvotes: 0

Rydion
Rydion

Reputation: 66

Depending on the order in which stuff is executed it may well be that

this.tService.setTs(form.value.member)

is being executed after

this.ts = tsService.getTs();

In which case the behaviour is expected.

As for how to deal with this problem. One way is to add a way for components to subscribe to the service and get notified when ts changes so that they can react by executing some code. Look into RxJS' Subject.

A different reason may be that you are not providing the service correctly.

For example if you provide the service to a parent and a child component (direct or not). In that case the second provider may be shadowing the first due to Angular's hierarchical dependency injection. Which means that one component is setting the value in one instance of the service and the other component is getting it from a different one. Unless you specifically need that kind of behaviour a service should only be provided at the root of the component tree where it's going to be used.

If your components are not related through the parent-child hierarchy then you should be providing the service only once. At the module level.

Without knowing more about your component structure it's not possible to tell what exactly is going on.

Upvotes: 1

Related Questions