Kyle Lee
Kyle Lee

Reputation: 23

Angular - How to Subscribe Data from Component to Component

enter image description hereI am trying to subscribe a data from a component. Somehow it's not working now, hope anyone can find out why...

app.component.html

<app-sample1></app-sample1>
<p></p>
<app-sample2></app-sample2>

sample1.component.html

<div class="main">
    <p>Sample1 !</p>
    Subsribed Title from Sample 2:
    <h3> {{titleFromSample2}}</h3>
</div>

sample2.component.html

<div class="main">
    <p>Sample2 !</p>
    <input type="text" #title (input)="change(title.value)">
</div>

sample.service.ts / sample1.component.ts / sample2.component.ts

enter image description here

When text value inserted in Sample2 Input box, 'change' method in sample2.componet.ts implements fine.

but titleFromSample2 values of sample1.component.ts and sample1.component.html are not changing.

I can't find what wrong is....

Upvotes: 2

Views: 3021

Answers (2)

Kari F.
Kari F.

Reputation: 1434

The problem is that the SampleService stores the title value but it does't emit new values. Change titleto title = new BehaviorSubject('');

Then in setTitle:

setTitle(value: string) {
  this.title.next(value);
}

That should do it.

Upvotes: 0

SiddAjmera
SiddAjmera

Reputation: 39432

That's because you are returning an Observable from getTitle which is unicast by nature. What that would mean is, it won't react to changes in the value of the title property in the SampleService.

To make it multicast, you'll have to use a Subject or a BehaviorSubject instead.

Something like this:

import { Injectable } from '@angular/core';
import { Observable, BehaviorSubject } from 'rxjs';

@Injectable()
export class SampleService {

  private title: BehaviorSubject<string> = new BehaviorSubject<string>(null);

  constructor() { }

  setTitle(value: string) {
    this.title.next(value);
  }

  getTitle(): Observable<string> {
    return this.title.asObservable();
  }

}

Also since this is going to emit multiple values over time and it's not really recommended to subscribe to Observables when they are emitting multiple values over time, you should be using the async pipe in the template instead.

So your Component would look like this:

import { Component, OnInit } from '@angular/core';
import { Observable } from 'rxjs';
import { SampleService } from '../sample.service';

@Component({
  selector: 'app-sample1',
  templateUrl: './sample1.component.html',
  styleUrls: ['./sample1.component.css']
})
export class Sample1Component implements OnInit {

  titleFromSample2$: Observable<string>;

  constructor(private sampleService: SampleService) { }

  ngOnInit() {
    this.titleFromSample2$ = this.sampleService.getTitle();
  }

}

And then in the template:

<div class="main">
    <p>Sample1 !</p>
    Subsribed Title from Sample 2:
    <h3> {{titleFromSample2$ | async}}</h3>
</div>

Here's a Working Demo for your ref.

Upvotes: 3

Related Questions