Exploring the use of Observables in Angular 2 services

Ensuring the seamless transfer of data between components is crucial in Angular development. One common way to achieve this is by utilizing observables. Let's take a look at how observables are implemented in a service:

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

}

In the parent component, data initialization happens within the onSelect() method:

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>
    <!-- Rest of the parent component template goes here --> 

Meanwhile, the child component should receive data from the subscriber. However, if the displayed data appears as undefined and results in a blank screen, we need to troubleshoot accordingly.

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) {
        // Subscribe to the observable for data retrieval
        mservice.stream1$.subscribe(value=>this.UiSelectedItem=value);
    }    
}

Answer №1

One essential tool to utilize is the Subject. If you're familiar with Angular's EventEmitter, you'll recognize that it functions similarly to a Subject. Typically, we use EventEmitter to relay events from child components to parent components.

@Component({
  template: `
    <child (textChange)="onTextChange()"></child>
  `
})
class ParentComponent {}

class ChildComponent {
  @Output() textChange = new EventEmitter();

  onClick() {
    textChange.emit('new value');
  }
}

If you have experience in using this pattern before, you understand the concept of publish/subscribe involved. Essentially, one entity subscribes to an event while another publishes it. This is where a Subject comes into play. It's worth noting that EventEmitter is a specific type of Subject.

In certain scenarios, relying solely on a vanilla Subject may not suffice. The issue arises when an event is emitted and no one is actively subscribed to it, resulting in missed notifications. To address this, consider using a ReplaySubject, which allows you to maintain a buffer with a customizable size to capture emitted events regardless of the timing of subscriptions.

Here's an implementation 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);
  }
}

To publish an item, simply set it within the service:

service.selectedItem = 'new item';

For components subscribing to this data:

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

Explore Further:


UPDATE

Demonstration available on Plunker

Answer №2

It is recommended to employ the Observable.create method in place of using new Observable

For more information, refer to: RxJs documentation

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

What is the best way to determine a comprehensive map of every sub-store, their functions, and what data they contain?

Summary: Can all actions with their payloads be automatically grouped by sub-store in a composite store using a single type entity (e.g., interface)? I have implemented a Redux store with multiple sub-stores structured as follows: There is an action setA ...

Tips for avoiding simultaneous state transitions in Angular UI Router

My situation in my Angular application involves a frustrating issue. Whenever a user double-clicks quickly on a link to a specific state (ui-sref link), the target state starts loading twice. This would be manageable if the state window didn't freeze ...

NativeScript encountered an error while trying to locate the module 'ui/sidedrawer' for the specified element 'Sidedrawer'

Currently, I am in the process of developing a simple side-drawer menu for my NativeScript application by following this helpful tutorial. I have successfully implemented it on a single page using the given code below. starting_point.xml: <Page xmlns ...

Attempting to retrieve backend data through an API to be displayed on the frontend

After successfully sending form data from my React front end to the server using fetch, I am struggling to make this data accessible from the front end again. Despite being able to access and utilize the data within my API function on the server side, I&ap ...

Excluding files in Angular by adding them to the .gitignore list

Interested in mastering the integration of Twilio with your Angular app? The first step is to configure your Twilio credentials and make sure to add that file to the .gitignore. However, upon reviewing this example Angular-Twilio project on GitHub, I notic ...

Navigating through Angular NGRX to handle looping over response data

// action export class LoadPlayersWinLoseCount implements Action { readonly type = PlayersActionTypes.LOAD_PLAYERS_WIN_LOSE_COUNT; constructor(public accountId, public queryParams, public payload?: IWinlose, ) {} } // reducer export function playersW ...

Managing the Sequence of HTTP Requests with RxJS

I have several REST requests that need to be executed in sequence, one after the other. At the completion of all requests, I also need to perform an additional action. I'm looking for a more efficient way to achieve this rather than cascading the re ...

Is it possible to import SVG files and inline them in Angular?

Behold, an SVG Circle: <svg viewBox="0 0 104 104"> <circle cx="52" cy="52" r="50" stroke="#003EFF" stroke-width="4" fill="#00FF98" /> </svg> The Angular Project imports it in this manner: import circle from './circle.svg'; ...

Unable to establish breakpoints in TypeScript within VS Code

I seem to be facing an issue while trying to set breakpoints in my TypeScript nodejs app using Visual Studio Code. Despite following the guidelines provided on the Visual Studio Code website, I have not been able to achieve success. Below is the content o ...

Mastering the intricacies of Angular bindings through intuition

I am attempting to grasp the concept of distinguishing between square brackets binding <elem [...]="..."><elem> and parentheses binding <elem (...)="..."<elem>. Is there a rule of thumb that can help differentiate between the two? Pe ...

Can you merge two TypeScript objects with identical keys but different values?

These TypeScript objects have identical keys but different properties. My goal is to merge the properties from one object onto the other. interface Stat<T, V> { name: string; description: string; formatValue: (params: { value: V; item: T }) =&g ...

Getting the Correct Nested Type in TypeScript Conditional Types for Iterables

In my quest to create a type called GoodNestedIterableType, I aim to transform something from Iterable<Iterable<A>> to just A. To illustrate, let's consider the following code snippet: const arr = [ [1, 2, 3], [4, 5, 6], ] type GoodN ...

Developing an Angular application and hosting it on an Apache server without the need

I am facing an issue where I need to share an Angular application with an external team, but they are encountering a 404 Not Found error when trying to load a page directly. Unfortunately, I do not have access to the Apache server where the application is ...

Retrieve an array of specific column values from an array of objects using Typescript

How can I extract an array from an array of objects? Data var result1 = [ {id:1, name:'Sandra', type:'user', username:'sandra'}, {id:2, name:'John', type:'admin', username:'johnny2'}, ...

Avoiding Maximum Call Stack Size Exceeded in Observables: Tips and Tricks

After filtering, I have a list stored in the variable filteredEvents$: public filteredEvents$ = new BehaviorSubject([]); I also have a method that toggles the checked_export property and updates the list: public checkAll(): void { this.filteredEve ...

What is the best method for typing a component prop that is compatible with singular use and can also function within loops without disrupting intellisense?

The Scenario Within a heading component, I have defined various types as shown below: // Heading/index.d.ts import { HTMLAttributes } from 'react'; export const HeadingType: { product: 'product'; marketing: 'marketing'; ...

Encountering issues with Proxy functionality in the latest versions of Angular 13 and Spring Boot

I've encountered an issue with the proxy configuration in Angular. I'm unsure if it's a problem within my Angular settings or if there's a configuration issue in Spring. For testing purposes, I have a backend built in springboot to han ...

Combine Immer and NgRx reducer for improved state management

Upon analyzing redux and ngrx, it appears that immer is the preferred library for creating a copy of the state before storing it. In following the example provided by immer, I implemented the following code in my reducer: on(exampleActions.updateExample ...

Error Encountered during Compilation of React TypesIs this okay

Currently, I am working on an MVC project that involves the use of TypeScript. To access the types required for this project, I have also integrated React. To obtain the React types, I performed an npm install --save-dev @types/react (similarly for react-d ...

Having trouble with TypeScript error in React with Material-UI when trying to set up tabs?

I have developed my own custom accordion component hook, but I am encountering the following error export default const Tabs: OverridableComponent<TabsTypeMap<{}, ExtendButtonBase<ButtonBaseTypeMap<{}, "button">>>> Check ...