Swap out a specific object within an observable array by comparing object properties

Currently, I am retrieving an observable array of custom IPix objects (Observable<IPix[]>) from a database using an API. After that, I update a record in the database by sending an edited version of the IPix object back to the API through a PUT request (based on legacyConfigTrackerId).

I am trying to figure out how to replace the original IPix object in the displayed array with the modified copy (based on legacyConfigTrackerId). This way, any changes made to the record will immediately show up in the table without needing to search or refresh.

However, I am having trouble filtering the array correctly. Every time I attempt to filter it, the result comes back as undefined and nothing gets displayed:

  pixRecords$!: Observable<IPix[]>;

  updatePix(pix: IPix) {
    console.log('update clicked');

    this.pixRecords$ = 
      this.pixRecords$.pipe(
        map((records: IPix[]) =>
          records.filter((p: IPix) => {
            p.legacyConfigTrackerId !== pix.legacyConfigTrackerId 

            // need to do something to replace the original object in the array with the 'pix' argument
          })
        )
      );

    pix.contract.effectiveDate = this.revertEffDateFormat();
    pix.contract.termDate = this.revertTermDateFormat();
    this.pixService.putPix(pix);
    this.formattedEffDate = '';
    this.formattedTermDate = '';
    this.closeModal.next(null);
  }

Since I am new to Angular, my approach might be incorrect. Any suggestions would be greatly appreciated.

Answer №1

When dealing with Observables, values are emitted and then disappear. A variable holding an Observable must be handled differently from other variables. It is not recommended to assign it directly (like this:

this.pixRecords$ = this.pixRecords$.pipe(...)
).

Instead, you have two options:

  • Store the emitted data in an array that can be manipulated in your code. (This is often the simplest approach.)
  • Utilize Observable features to hold onto the data and manipulate it within a pipeline.

For the latter option, there are various strategies:

  • Use the scan operator to keep the emitted array of data and make changes to it as needed.
  • Employ a BehaviorSubject to emit the fetched array from the http call into a BehaviorSubject, which remembers its last emission.

Here is a sample using the scan operator:

  products$ = this.http.get<Product[]>(this.productsUrl)
    .pipe(
      tap(data => console.log('Products: ', JSON.stringify(data))),
      catchError(this.handleError)
    );

  private productInsertedSubject = new Subject<Product>();
  productInsertedAction$ = this.productInsertedSubject.asObservable();

  allProducts$ = merge(
    this.products$,
    this.productInsertedAction$
  ).pipe(
    scan((acc, value) =>
      (value instanceof Array) ? [...value] : [...acc, value], [] as Product[])
  )

In this example, the retrieved products are emitted to the products$ Observable, while the UI binding is done through the allProducts Observable.

The productInsertedAction emits any newly added product. The addProducts$ Observable triggers whenever a new product is added.

By using the scan operator, the previous array of products is retained, allowing the code to reference it (as the acc variable) and make additions.

This code structure could be extended to include update and delete functionalities.

If you're new to Angular, I've included a link to an introductory video on RxJS for further exploration: https://youtu.be/vtCDRiG__D4

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

I am sorry, but there seems to be an issue with the JSON input as it is ending

Whenever I try to submit the form in edit mode, I encounter two errors. An unexpected end of JSON occurred Input provided caused an unexpected end of JSON The update process works perfectly fine and successfully saves values in the database. However, I ...

Does Typescript extend Node.js capabilities?

I am currently developing an application using Typescript and came across some sample Node.js code online. Can I directly use the Node.js code in my Typescript application? Essentially, I am wondering if Typescript is encompassed within Node.js. A simila ...

What is the best way to free up memory after receiving responseText in a continuous streaming request?

Utilizing xmlHTTPRequest to fetch data from a continuous motion JPEG data stream involves an interesting trick where responseText can populate data even before the request is completed, since it will never actually finish. However, I have encountered some ...

Implementing Adsterra in your next.js or react.js project: A step-by-step guide

Currently, I am working on integrating the Adsterra Banner 300x50 into a ts/js reactjs + nextjs project. The provided script code from Adsterra is as follows: <script type="text/javascript"> atOptions = { 'key' : 'XXXXXX&a ...

There are a pair of Ionic2 menus; one is currently visible while the other remains hidden

I am having an issue with my Ionic2 app where I have two pages, each with similar menus named XXX.html. One page displays its menu correctly, but the other does not show its menu at all. Is there a limitation in Ionic2 that prevents having two menus on the ...

One way to consolidate multiple components in a single location without altering user-input data

I currently have 3 separate components, namely PersonalInfoComponent, EducationalInfoComponent, and ExperienceComponent. These components are all being displayed within the ResumeComponent. The issue I am facing is that when a user enters information in t ...

Converting a string to a data type in Typescript: A beginner's guide

I'm currently in the process of developing various web components, each capable of emitting custom events. To illustrate, here are a couple of straightforward examples: //MyButton emits 'myButtonPressed' with the following details: interfac ...

"Error occurs as a result of an unspecified attribute in the map

Hello, I am currently traversing a tree structure recursively. To handle undefined nodes in the tree, I have implemented guards to prevent any failures. However, during the mapping of children nodes, I encountered the following error: Error Output Adri ...

Children must be matched to the route before navigating to it

Hello there! I'm having trouble understanding how to navigate new routes with children in Angular 2 rc 4. I'm trying to route to the TestComponent, which has a child, but I keep getting an error message saying "cannot match any route 'test&a ...

The API call retrieval encountered an issue due to CORS, as the nginx configuration settings were not correctly

Greetings and thank you for your valuable time I am currently running a dotnet core web api application on port 6000, alongside an angular application. I have set up nginx to reverse proxy to the dotnet core application, and to the angular application ...

Issue encountered while attempting to package Azure project in Visual Studio 2015 Update1 due to difficulty copying Typescript files

Since upgrading to VS 2015 Update 1 (that includes Typescript 1.7) and Azure SDK 2.8, packaging my Azure application for deployment has become a challenge due to an error in the file path where the packager is attempting to copy the js output file: Erro ...

Exploring Jasmine and Karma for testing Angular 5 HTTP requests and responses

I am brand new to the concept of Test-Driven Development (TDD) and I am currently in the process of debugging a complex Angular 5 application for the company I work for. The application is functioning without any issues, but now I need to incorporate test ...

Guide to configuring a function to display the maximum value on a boxplot in Highcharts

I'm currently using Angular in combination with the highcharts boxplot API. While I am aware that I can manually set the max value of the y-axis in the chart configuration, such as: max: 100, tickInterval: 10. There's now a need for me to dynami ...

Nearly every category except for one from "any" (all varieties but one)

In Typescript, is it feasible to specify a type for a variable where the values can be any value except for one (or any other number of values)? For instance: let variable: NOT<any, 'number'> This variable can hold any type of value excep ...

Replace the function if it is specified in the object, otherwise use the default functionality

Having a calendar widget written in TypeScript, I am able to bind a listener to a separate function. However, I desire this separate function to have default functionality until someone overrides it in the config object passed to the constructor. Within th ...

Steps for creating a table with a filter similar to the one shown in the image below

https://i.sstatic.net/zR2UU.png I am unsure how to create two sub-blocks within the Business A Chaud column and Potential Business Column. Thank you! I managed to create a table with input, but I'm struggling to replicate the PUSH & CtoC Column for ...

Is there a way to insert a Highchart Image into a spreadsheet in Excel?

Struggling to insert a Highchart's chart image into an Excel file? The goal is to utilize the current "Export Excel" button on a website to export a static image of the Highchart displayed on the webpage directly into an excel spreadsheet. Provided be ...

Interactive form control for location details including country, state, district, and town

I am struggling with adding dynamic form controls on dropdown change. I have been able to add them, but encountered an error preventing me from retrieving the value in 'formName.value'. The specific error message states: "Error: There is no Form ...

Angular material table cell coloring

Here is my current setup: I have an array of objects like this: users : User []; average = 5; compareValue (value){ ...} And I am displaying a table as shown below: <table mat-table [dataSource]="users"> <ng-container matColumnDef= ...

Tips for typing a destructured object key in TypeScript

Assuming I have a query parameter from the router in my Next.js app const { query: { id }, } = useRouter(); The value of { id } is currently string | string[] | undefined. I want to send it as a parameter to another function, and I am certain that ...