coder007 coder007 - 1 year ago 123
AngularJS Question

Angular 2 trying to implement Observables in services

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'

export class SelectedItemService {

stream1$= new Observable(observer=> setTimeout(() => {;
}, 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'

selector: 'newcomponent',

<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" >
<label for="link">Link:</label> <input name="link"></form>
<div class=container *ngFor="let data of dataServer"
[class.selected]="data === selectedItem"
<div id="myimages">
<a routerLink="/SecondNewCom">
<img src="myBaseurl/{{data.images.image3}}">
<div class=caption> {{data.productName}} </div>
styleUrls: [`./app/mydoc.css`]
export class NewComponent {
nameValue: string;
lists: string[];

constructor(private http:Http, public myservice:SelectedItemService) {
this.nameValue = "declaredName";
this.lists = ['abc', 'xyz', 'lol'];
this.http.get(this.url).map((res:Response) => res.json())
data => { this.dataServer = data
err => console.error(err),
() => console.log('done')


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'

template:`<h1> This is second new Component</h1>

export class SecondComponent{

constructor(public mservice:SelectedItemService) {

Answer Source

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

  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) {;

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:


See Plunker

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download