Tips on using services for storing and fetching list data in Angular

I currently have two components, the "add-expense" component and the "view-list" component. The "add-expense" component collects expense details from a form and stores them as an object. My goal is to add this object to an empty list within the "expense-list" service. When I later load my "view-list" component, all the values in the list maintained by the "expense-list" service should be displayed.

I've read about using rxjs BehaviorSubject for this purpose. However, most examples demonstrate how to store and update strings using .next(). In my case, I need to work with a list.

import { BehaviorSubject } from "rxjs";
export class ExpenseListService{
    expenseList:BehaviorSubject<any[]> = new BehaviorSubject([]); //error
    
}

How do I define a BehaviorSubject that takes a list as its type? How can I add/push elements to this list maintained by the BehaviorSubject? And how do I subscribe to changes?

Answer №1

It's strange that you're encountering an error with that code because it runs smoothly on my end. Check out the code here

If you have a behavior subject containing an array and you need to add a new value to it, you can utilize the spread operator to create a new array with the additional item.

export class ExpenseListService{
  expenseList:BehaviorSubject<any[]> = new BehaviorSubject([]);
    
  add(item) {
    this.expenseList.next([...this.expenseList.value, item]);
  }
}

This action will trigger the behavior subject to emit a fresh array inclusive of the newly added value.

Answer №2

When you initialize a variable with an assertion, there is no need to explicitly set the type as it will be determined by the value you provide.

For example, you can simply write:

expenseList = new BehaviorSubject([]);

However, it is considered best practice to specify the type of the array like so:

expenseList = new BehaviorSubject<ListModel[]>([]);

If you want to append data to the existing array, you should do it as follows:

const newValue = 'new value';
const newContent = [...this.expenseList.getValue(), newValue];

this.expenseList.next(newContent)

To subscribe to the observable:

 expenseList.asObservable().subscribe(() => ....) 

Answer №3

Edit: AdrianBrand's Solution is more concise and appropriate, and I recommend using it

If my understanding is correct, you are looking to:

  1. add a single object from the "add-expense" component to an array
  2. subscribe to an observable in your "view-list" and retrieve the array containing all previously added values?

Using a BehaviourSubject as you suggested may not be effective, as it would result in emitting a new array each time and losing the previously added values.

I believe a straightforward store approach would be most suitable: (Caution: This method only appends values to the list if the observable is subscribed to.)

export class ListService {
  // No initial value:
  private expenseListSubject: Subject<any> = new Subject<any>();
  // The empty initial array:
  private initialList = [];

  // Pass the emitted subject values through scan to accumulate them:
  public expenseList$: Observable<any[]> = this.expenseListSubject.pipe(
    scan((acc: any[], currentValue: any) => ([...acc, currentValue]), this.initialList)
  );
  
  public addToList(value: any) {
    this.expenseListSubject.next(value)
  }
}

To subscribe in your component:

export class ViewList {
  constructor(private listService: ListService) {}
  
  this.listService.expenseList$.subscribe((currentArray) => console.log(currentArray))
  }

To append a new value:

export class AddExpense {
  constructor(private listService: ListService) {}

  this.listService.addToList(value)
  }

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

Tips for retrieving next-auth authOptions from an asynchronous function

I need to retrieve values from AWS Secrets Manager and integrate them into the authOptions configuration for next-auth. The code implementation I have is as follows: export const buildAuthOptions = async () => { const secrets: AuthSecrets = await getS ...

Tips for implementing <mat-progress-bar> in .ts file when making API service requests with Angular

I'm currently utilizing an API call to retrieve an image from a service, and I would like to display a progress bar while the image is being fetched. It seems that I need to incorporate the progress bar within the service as the image data is returned ...

The Angular Karma tests are failing because the custom tag is not recognized as a known element

I've recently started learning Angular and encountered an issue with my first Karma test. The error message I received is as follows: AppComponent should create component Error: Template parse errors: 'ereturn-form' is not a known element: ...

Stop the MatSort feature from activating when the space key is pressed in Angular Material

I am currently using angular material tables and have implemented filters for each column. The filter inputs are located in the row header of each column, which is working fine. However, I am facing an issue where whenever I type and press the space key, ...

Following the build in Angular, it only displays the index.html file and a blank screen

According to the information on Angular's official website, running the "ng build" command should generate files in the dist folder ready for hosting. However, after running this command, the index.html file is empty except for the page title. When yo ...

Flex mode allows for responsive row details in ngx-datatable

Having an issue with my ngx datatable row details. Everything works well initially, but when I adjust the browser width, the details don't scale properly with rows and columns. They seem to have a fixed width that was set when the page was first loade ...

Issue with updating state in child component preventing addition to state

Recently, I made the switch to TypeScript in my NextJS project using Create T3 App. One of the components in my app involves updating the state after a Prisma mutation is performed. I attempted to pass the setItems (which was initialized with useState) to ...

Navigating through an array's contents with RxJs

Is there a more efficient way to iterate over an array fetched from an observable using RxJS operators in order to generate and emit new individual ListingItem objects? onGetItemData(){ this.dataService.getItemData().subscribe((itemData) => { this.it ...

Implementing automatic selection for MUI toggle buttons with dynamic data

By default, I needed to set the first toggle button as selected import * as React from "react"; import { Typography, ToggleButton, ToggleButtonGroup } from "@mui/material"; export default function ToggleButtons() { const dat ...

Guide on displaying toaster notifications using promises in Angular 2

Hey everyone, I've encountered a problem with promises while handling a 500 internal server error. I have set up Promises to handle post and get services, but when catching the 500 response, I can't seem to display it in a toaster. Here's my ...

The correct way to add to a string array that has been passed as props to a functional component

There is a parent component that establishes a useState hook with a string array. Then, there is a child component tasked with updating the string array. To accomplish this, both the string array and the useState function are passed to the child component. ...

Traversing the enum's keys poses a challenge in terms of typing

Imagine you need to display all values of an enum enum AnEnum { a = 'a', b = 'b' } const keys = Object.keys(AnEnum); keys.forEach(key => { console.log(AnEnum[key]); }); This results in the following error message: ...

Preview of Azure AD Consent Scopes and Access Token Version Error in Msal Angular

Currently in the process of updating my web application with the new MSAL library, @azure/msal-angular, from previously using the old ADAL library. The frontend of the web app is built with Angular 5 and communicates with a backend ASP.NET Core Web API. ...

Adding dynamic row values to a bootstrap table in angular 4 - what's the best approach?

When using an Angular 4 bootstrap table, I am encountering an issue where only the first row value is displayed in the table from the backend when entering a product in the text box and pressing enter. Even though the alert window shows the data for the se ...

Learn how to restrict input to only specific characters in an input box using Angular2 and validations

Is it possible to restrict user input in an input box to only specific characters such as '7' and '8'? I tried adding validations with attributes like type="number", min="7" and max="8", but even then other keys can be inserted before v ...

Incorporate the Materialize framework into an Angular 2 project using webpack and SCSS styling

Looking to incorporate Materialize into my Angular 2 project but facing some challenges The project was set up using "AngularCli" and it utilizes "Webpack" and "Scss" I have come across various tutorials for integrating Materialize, but none specificall ...

Utilize JSON Objects rather than JSON arrays when using JSON-SERVER

Currently, I am utilizing json-server to transform JSON data into a REST API. Whenever a GET request is made like this: http://localhost:3000/items?itemid=534 The server responds with: [ { "itemid": 534, "type": "textcontent", "icon": "ht ...

Even after importing the API key, I am still receiving the message "This domain is not registered with Tiny Cloud."

I have implemented the TinyMCE code provided in their documentation: <editor [init]="{ apikey: '<secret>', height: 500, plugins: [ 'a11ychecker','advlist','advcode','advtable',&apos ...

What causes an error during the compilation of an Angular package containing a singleton class?

I am currently in the process of creating an Angular library. Within this library, I have developed a singleton class to manage the same SignalR connection. Here is the code implementation: import * as signalR from '@microsoft/signalr'; export c ...

HTTP request in Angular with specific body content and custom headers

My goal is to access the sample API request from , as demonstrated in the documentation: curl -H "api-key: 123ABC" \ -H "Content-Type: application/json" \ -X POST \ ...