问题
Im trying to send data from one component to other using observable. Here I'm implementing observable in service like this...
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs/RX'
@Injectable()
export class SelectedItemService {
stream1$:Observable<any>;
selectedItem:JSON;
stream1$= new Observable(observer=> setTimeout(() => {
observer.next(this.selectedItem);
}, 3000);)
}
and my parent Component is initializing data to a service in onselect() like below :
import { Component } from '@angular/core';
import {Http, Headers,Response } from '@angular/http';
import {Observable} from 'rxjs/Rx';
import 'rxjs/add/operator/map';
import {SelectedItemService} from './selecteditem.service'
@Component({
selector: 'newcomponent',
template:`<p>
</p>
<h2>Your Title: {{nameValue}}</h2>
<ul><li *ngFor="let list of lists">Hello {{ list }}</li></ul>
<form class="ui large form segment">
<h3>Add a Link</h3> <div>
<label for="title">Title:</label>
<input [(ngModel)]="nameValue" placeholder="title" name="Title" >
</div>
<label for="link">Link:</label> <input name="link"></form>
<div class=container *ngFor="let data of dataServer"
[class.selected]="data === selectedItem"
(click)="onSelect(data)">
<div id="myimages">
<a routerLink="/SecondNewCom">
<img src="myBaseurl/{{data.images.image3}}">
</a>
<router-outlet></router-outlet>
</div>
<div class=caption> {{data.productName}} </div>
</div>`,
styleUrls: [`./app/mydoc.css`]
})
export class NewComponent {
nameValue: string;
lists: string[];
url:string;
dataServer:JSON[];
length:number;
selectedItem:JSON;
constructor(private http:Http, public myservice:SelectedItemService) {
this.myservice=myservice;
this.nameValue = "declaredName";
this.url="myBaseurl";
this.lists = ['abc', 'xyz', 'lol'];
this.http.get(this.url).map((res:Response) => res.json())
.subscribe(
data => { this.dataServer = data
this.length=Object.keys(this.dataServer).length},
err => console.error(err),
() => console.log('done')
);}
onSelect(data:JSON):void{
this.selectedItem=data;
this.myservice.selectedItem=data;
}
}
and child component is receiving the data from subscriber like this... but the data displayed is undefined and i see blank screen.. Where am i doing wrong...
import {Component,Input} from '@angular/core';
import {SelectedItemService} from './selecteditem.service'
@Component({
selector:'secondcomponent',
template:`<h1> This is second new Component</h1>
<h1>{{UiSelectedItem}}</h1>
`
})
export class SecondComponent{
UiSelectedItem:JSON;
constructor(public mservice:SelectedItemService) {
this.mservice=mservice;
mservice.stream1$.subscribe(value=>this.UiSelectedItem=value);
}
}
回答1:
What you should be using is a Subject. If you have ever used Angular's EventEmitter, this is also a Subject. With EventEmitter we usually use it to publish events from child to parent
@Component({
template: `
<child (textChange)="onTextChange()"></child>
`
})
class ParentComponent {}
class ChildComponent {
@Output() textChange = new EventEmitter();
onClick() {
textChange.emit('new value');
}
}
It's you've ever used this before, this is is the publish/subscribe pattern that you need. Someone subscribes to the event, and someone publishes it. This is where we can use Subject. As I said EventEmitter is a subclass of Subject.
For this case though, the vanilla Subject may not be good enough. The reason is that once the event is emitted, it is gone forever. If there was no one subscribed, nothing happens with it. So if it happens that you subscribe just a smidget after the event was emitted, then you get nothing. A lot of times this is unacceptable.
For this case, we can use a ReplaySubject. This type of subject allows you to keep a buffer with configurable size. So if you subscribe right after the event was emitted you will still get it.
Here's an example
import { ReplaySubject } from 'rxjs/ReplaySubject';
export class SelectedItemService {
private _selectedItem = new ReplaySubject<string>(1); // buffer size 1
selectedItem$ = this._selectedItem.asObservable();
set selectedItem(item: string) {
this._selectedItem.next(item);
}
}
Now the component that wants to publish just needs to set the item
service.selectedItem = 'new item';
And the subscribing component
service.selectedItem$.subscribe(item => {})
See Also:
- What are RxJS Subject's and the benifits of using them?
- RxJS docs on Subjects
UPDATE
See Plunker
回答2:
You should use Observable.create instead of new Observable
See : RxJs docs
来源:https://stackoverflow.com/questions/39895805/angular-2-trying-to-implement-observables-in-services