update a property of a live object using an API request

Below is a sample of the service function I am working with:


getByIdWithCategory(id: number): Observable<Product> {

    const category = new Category();
    category.name = 'sample category';

    return this.httpClient.get<Product>(this.baseUrl + `/${id}`)
      .pipe(map(product => ({...product, category})));
  }

In my template file, I retrieve the value returned from this function using the async pipe. However, I also need to obtain the category from the API, which requires subscribing. The challenge is in finding the best practice for unsubscribing from this call.

The following function meets my requirements perfectly. Nevertheless, I am struggling to unsubscribe from the API call used to retrieve the category.

  getByIdWithCategory(id: number): Observable<Product> {

    return this.httpClient.get<Product>(this.baseUrl + `/${id}`)
      .pipe(
        tap(product => {
          this.categoryService.getById(product.id)
            .subscribe(category => {
              product.category = category;
            });
        })
      );
  }

My product class structure looks like this:

export class Product {
  id: number;
  title: string;
  price: number;
  description: string;
  categoryId: number;
  image: string;

  category: Category;
}

Answer №1

Avoid the use of nested subscriptions, especially subscribing inside the tap operator as it can make your code appear messy. A better approach would be to utilize switchMap to map from one observable to another, and then pipe map to the inner observable in order to return the entire object with the category property.

Give this a try:

getByIdWithCategory(id: number): Observable<Product> {
  return this.httpClient.get<Product>(this.baseUrl + `/${id}`).pipe(
    switchMap((product: Product) => {
      this.categoryService.getById(product.id).pipe(
        map((category: Category) => ({
          ...product,
          category: category
        }))
      )
    })
  );
}

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 are the steps to prevent exceptions from being displayed when an Angular project times out?

Despite the absence of a debugger or breakpoints provided, the execution halts here whenever the Angular project is logged out due to timeout. https://i.sstatic.net/OFsvI.png ...

While utilizing the imodel.js front-end for designing a custom geometric model, I ran into an issue while trying to display it

Utilizing imodel.js front-end, I was able to design a customized geometric model featuring elements like a collection box. However, when placing the model within the existing SpatialViewState in bim, it failed to display properly in the current view. Sub ...

Passing a variable correctly with Route in Angular Ionic 4 - Best Practices

I am looking to seamlessly pass a variable from the movie-list page to another subpage titled movie-series. movie-list.page.html: <ion-content> <ion-list> <ion-item *ngFor="let item of items" [routerLink]="['/movie-series ...

Differences Between Angular Event Emitter and Click Listener

I've been delving into Angular by exploring the "Your First App" section on their official website. One aspect that has caught my attention is the event emitter functionality. In the Parent Component (product-list): <app-product-alerts [produc ...

Retrieving information stored in a FormBuilder through the HTML

Once I set up a FormBuilder during the onInit Lifecyle: surveyForm: FormGroup; ngOnInit(): void { this.surveyForm = this.formBuilder.group({ 'surveyTitle': new FormControl(null), 'surveyDescription': new FormControl(n ...

Guide on utilizing TypeScript with dynamic object keys

I have a State object that keeps track of time in days, hours, and minutes. The state is defined as follows: type StateKeys = "days" | "hours" | "minutes"; type State = { [K in StateKeys]: number }; Now, I need to update the state based on user inpu ...

Is it possible to deactivate the click event on an Angular mat table row?

Within my Angular mat table, I have implemented code that expands a table row when clicked. However, I now need to prevent certain rows from being clickable based on the "element.disable" property. <ng-container matColumnDef="id"> <th mat-hea ...

"Exploring the incredible powers of Ionic2, Angular2, HTTP requests, and

Despite all the research I've done on observables, I still struggle to grasp how they function. The HTTP request code snippet is as follows: import { Component, OnInit, Injectable } from '@angular/core'; import { Http, Response, Headers, R ...

Creating a method in Angular that combines async/await functionality with Observables

After transitioning from using async/await to Observables in Angular, I am trying to refactor the following code snippet to make it work with Observables: async refreshToken() { const headers = this.authStorage.getRequestHeader(); const body = { ...

What sets *ngTemplateOutlet apart from [ngTemplateOutlet]?

Here is a unique explanation that is not a duplicate of the answers provided in this post or the correct explanation of the asterisk operator found here. However, it does build on the information presented in those posts. The concept of *ngBeep as a conve ...

Utilizing Protractor's advanced filtering techniques to pinpoint the desired row

I am trying to filter out the specific row that contains particular text within its cells. This is my existing code: private selectTargetLicense(licenseName: string) { return new Promise((resolve => { element.all(by.tagName('clr-dg-tab ...

Remove an element from an array within objects

Need help with removing specific items from an array within objects? If you want to delete all hobbies related to dancing, you may consider using the splice method const people = [{ id: 1, documents: [{ ...

Typescript fails to recognize a value assigned within an await statement

Looking at the code snippet below, we see that the variable x starts off undefined and can later be assigned a value of 1 within an `await` promise. Despite setting x to 1 inside the awaited promise, TypeScript still perceives it as undefined after the pr ...

Customizing event typings for OpenTok in Typescript

Currently, I am working on integrating chat functionality using the 'signal' events with the OpenTok API. Here is my event listener that successfully receives the signal: // Listen for signal CHAT_MESSAGE sess.on('signal:CHAT_MESSAGE', ...

How can I place an icon on a specific location in a Highcharts map?

I am currently utilizing Highcharts to showcase maps within my application. I am aiming to achieve two specific functionalities: 1) Upon clicking on any area, I want that area to be highlighted in red {completed} 2) Upon clicking on any area, I intend f ...

Ways to enhance focus on childNodes using Javascript

I am currently working on implementing a navigation system using a UL HTML Element. Here's the code I have so far: let htmlUL = <HTMLElement>document.getElementById('autocomplete_ul_' + this.name); if (arg.keyCode == 40) { // down a ...

Guide on subscribing to an object from a service in Angular 2/5

I am facing an issue where I need to update my property component with data received from the server. In the Service, I have implemented something like this: private events: Event[] = []; eventChanged = new Subject<any>(); // Edit: added an observa ...

Updating Angular 8 Component and invoking ngOninit

Within my main component, I have 2 nested components. Each of these components contain forms with input fields and span elements. Users can edit the form by clicking on an edit button, or cancel the editing process using a cancel button. However, I need to ...

Modify the Text Displayed in Static Date and Time Picker Material-UI

Looking to update the title text on the StaticDateTimePicker component? Check out this image for guidance. In the DOM, you'll find it as shown in this image. Referring to the API documentation, I learned that I need to work with components: Toolbar ...

Issues with Font Awesome fonts failing to load after compiling an Angular project using `ng build`

I've encountered an issue with Angular 8 and Font Awesome icons. I initially added the font-awesome path in the angular.json as follows: "./node_modules/font-awesome/css/font-awesome.css" However, all the icons were displaying as empty boxes (not lo ...