Angular 2 tries to implement Observables in services

I am trying to send data from one component to another using an observable. Here I implement observables in a 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 initializes the data to the service in onselect (), as shown 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 the child component receives data from the subscriber like this ... but the displayed data is undefined and I see a 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); } } 
+5
source share
2 answers

What you should use is Subject . If you've ever used an Angular EventEmitter , this is also a Subject . With an 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'); } } 

That you have ever used this before, this is the publish / subscribe template you need. Someone subscribes to the event, and someone publishes it. Here we can use Subject . Like I said, EventEmitter is a subclass of Subject .

In this case, the Vanilla Subject may not be good enough. The reason is that as soon as an event is emitted, it disappears forever. If no one has signed up, nothing happens to him. So if it happens that you only subscribed to smidget after the event has been issued, then you will not receive anything. Many times this is unacceptable.

In this case, we can use ReplaySubject . This type of object allows you to save a buffer with a custom size. Therefore, if you signed up immediately after the event was released, you will still receive it.

Here is 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 element

 service.selectedItem = 'new item'; 

And the subscription component

 service.selectedItem$.subscribe(item => {}) 

See also:


UPDATE

See Plunker

0
source

You should use Observable.create instead of new Observable

See: RxJs Documents

0
source

Source: https://habr.com/ru/post/1257793/


All Articles