0

I am trying to update a variable declared in my component when the variable declared in my service changes. I am using Subject for this. However, nothing happens.

app.module.ts

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';


import { AppComponent } from './app.component';
import { ShareDataService } from './share-data.service';


@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule
  ],
  providers: [ShareDataService],
  bootstrap: [AppComponent]
})
export class AppModule { }

app.component.ts

import { Component } from '@angular/core';
import { ShareDataService } from './share-data.service';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  title = 'app';
  _subscription;
  constructor(private shareDataService:ShareDataService)
  {
    //this.title=this.shareDataService.title;
    this._subscription = shareDataService.titleChange.subscribe((value) => { 
      this.title = value; 
      //alert(this.title);
      console.log("COmponent::::::::::::::"+this.title);
    });
  }
}

shareDataService.ts

import { Injectable } from '@angular/core';
import { Subject } from 'rxjs/Subject';
@Injectable()
export class ShareDataService {
  title:string="TITLE";
  titleChange: Subject<string> = new Subject<string>();
  constructor() {
    setTimeout(
      function()
      {

      this.title="BACDEF";

      //console.log(this.title);
      this.titleChange.next(this.title);
    }
    ,1000);
   }
}

It gives an error saying "Cannot read property 'next' of undefined" for the Subject defined in service. What would be the most appropriate way to implement this?

2 Answers 2

1

Use arrow function:

setTimeout(() => {
  this.title="BACDEF";
  this.titleChange.next(title);
}, 1000)

or bind:

setTimeout(function() {
  this.title="BACDEF";
  this.titleChange.next(title);
}.bind(this), 1000)

to get rid of that error. Otherwise this in setTimeout's callback is a window object

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

2 Comments

what's the best way to inform component about changes in multiple variables of a service? Is using Subject the best way?
Subject is a natural (I would say) way to inform components about changes. And as @cyberpirate92 wrote, most likely you need a BehaviorSubject. Because when you inject a service, component's constructor needs an instance of that service. And because services doesnt have life cycle hooks - only the constructor method, your component gets that instance when service's Subject already received next(). In other words - constructor subscribes after service calls next() on Subject. But if you use BehaviorSubject, it remembers the last value.
1

What would be the most appropriate way to implement this?

You can use a BehaviorSubject instead of a Subject, because

  • Upon subscription BehaviorSubject returns the last value whereas the Subject doesn't trigger until onnext, So using a BehaviorSubject you don't have to be worried about your components having the latest data, no matter when you subscribe.

  • If you want to retrieve the last value of the BehaviorSubject in a non-observable code (without a subscription), you can always use the getValue() method.

StackBlitz

Comments

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.