Reputation: 23
I 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
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
Reputation: 1434
The problem is that the SampleService stores the title value but it does't emit new values. Change title
to title = new BehaviorSubject('');
Then in setTitle:
setTitle(value: string) {
this.title.next(value);
}
That should do it.
Upvotes: 0
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 Observable
s 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