What is the best way to easily update multiple properties on objects received from an Observable?

My API is returning a large array of objects (categories), ranging from 50 to 200 categories at once. To handle this, I am creating a source observable that filters all categories into two sub-categories and presents them as separate properties within a single object.

public allCategories$: Observable<any> = this.categoryService.getAllCategories()
  .pipe(
    map((allCategories: CategoryModel[]) => {
      const red = allCategories.filter((cat) => cat.color === 'red');
      const blue = allCategories.filter((cat) => cat.color === 'blue');
      const allCats = { red, blue };
      return allCats;
    }),
    publishReplay(1),
    refCount()
  )

I then utilize the async pipe in Angular to subscribe and iterate over each stream representing red/blue categories using separate ngFors.

In my UI, each category corresponds to a checkbox. Users can search through all categories, check the checkboxes for specific ones, and then submit these selected categories with parameters to be processed elsewhere.

The challenges I am encountering include:

  • These user interactions occur in two areas on the same page: a modal and a typeahead component.
  • Both components should be able to read and write to the source observable without affecting the database or permanently changing state for these two components.
  • I am struggling to figure out how to update the objects being pushed down after the subscription has started, as it does not seem efficient to continually push 50-200+ objects to a Subject whenever a checkbox is modified.

I have explored more complex rxjs patterns, but they seem excessive for the already complex angular application I am working on. What would be a simple yet effective architecture for managing this scenario?

Answer №1

It seems that in solving your issue, the use of rxjs is unnecessary as all data can be effectively stored within a single component, even when employing multiple methods for selecting said data.

The solution would involve adding a property to the component to store the ids of selected categories, without being dependent on the categories data stream or rxjs.

class MyComponent {
  public allCategories$: Observable<any> = this.categoryService.getAllCategories().pipe(
    map((allCategories: CategoryModel[]) => {
      const red = allCategories.filter((cat) => cat.color === 'red');
      const blue = allCategories.filter((cat) => cat.color === 'blue');
      const allCats = { red, blue };
      return allCats;
    }),
    publishReplay(1),
    refCount()
  );

  // here we will store selected ids
  public selectedCategories: Array<string> = []; // array of ids.

  // our callback to handle selection
  public toggleCategory(id: string) {
    if (this.selectedCategories.indexOf(id) === -1) {
      this.selectedCategories = [
        ...this.selectedCategories,
        id,
      ];
    } else {
      this.selectedCategories = this.selectedCategories.filter(v => v !== id);
    }
  }

  // our callback how to save selection
  public submit() {
    this.categoryService.send(this.selectedCategories); // doing something.
  }
}

In the template, implement the following:

<ng-container *ngIf="allCategories$ | async as categories">
  <div *ngFor="let category of categories.red">
    <!-- No need for rxjs to manage selection -->
    <input type="checkbox" (click)="toggleCategory(category.id)" [checked]="selectedCategories.indexOf(category.id) !== -1"> {{ category.name }}<br>
  </div>

  <div *ngFor="let category of categories.blue">
    <input type="checkbox" (click)="toggleCategory(category.id)" [checked]="selectedCategories.indexOf(category.id) !== -1"> {{ category.name }}<br>
  </div>

  <button (click)="submit()">Save chosen categories</button>
</ng-container>

If there is a need to share selections between components, separate service endpoints can be established for toggling and fetching selections. In such cases, using

combineLatest([this.allCategories$, this.selectedIds$])
could be beneficial.

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

Using the Angular 4 filter pipe in conjunction with server-side pagination functionality

When using filter with pagination, the issue arises where searching for a Name filters the results but the pagination remains static. This means that if the search returns 3 filtered records, the pagination will still display multiple pages for navigation. ...

What is the best way to execute an asynchronous request within a CanDeactivateFn guard in Angular?

Here's a strange question I've been grappling with lately. So, I've got this function that essentially creates a custom Alert Window to handle unsaved form data when a user tries to navigate away. It may or may not be triggered depending on ...

The recommended filename in Playwright within a Docker environment is incorrectly configured and automatically defaults to "download."

Trying to use Playwright to download a file and set the filename using download.suggestedFilename(). Code snippet: const downloadPromise = page.waitForEvent('download', {timeout:100000}) await page.keyboard.down('Shift') await p ...

How to Bring in a Json File in Angular 6?

Trying multiple methods to import a JSON file, but encountering the error: countries.json has unknown extension. Is there a possible solution that I am overlooking? The current tsconfig setup is as follows: "compileOnSave": false, "com ...

Customize the position values of the Ngx-bootstrap Tooltip manually

I have incorporated ngx-bootstrap into my Angular 4 application. The component I am using is ngx-bootstrap Tooltip: After importing it, I am implementing it in my component's view like this: <button type="button" class="btn btn-primary" ...

Loading pages in real-time with parameters (Using Ionic 2 and Angular 2)

I'm in the process of developing a recipe app that features various categories which I want to load dynamically upon click. To retrieve recipes, I have a URL (HTTP GET request) that I intend to modify by adding a specific string based on the category ...

primeng allows for implementing a table filter functionality with a dropdown selection

I am working with a p-table from primeng and attempting to synchronize the selection from the dropdown menu with the filter method of the table, but I have not been successful in achieving this. Could you please help me identify the issue? <p-table ...

Struggling to link dropdownlist with an array fetched from my service - need assistance

One of my services includes a method that retrieves a list of employees: export class EmployeeService { private employeesUrl = 'http://localhost:portnum/api/employees'; getEmployees(): Observable<IEmployee[]> { return th ...

Access a router and showcase a new URL in the browser using Angular 2

When using the router.navigate method to navigate to a specific path, it is possible to display a different URL in the browser than the one being navigated to. For example, if I want to navigate to the path /open/quote using this.router.navigate(['/o ...

Changing the value of a variable in RxJS filter operator when a certain condition is satisfied

I am facing an issue with my code where the setDischarges method is not being executed if the condition in the filter (!!discharges && !!discharges.length) is met. loading: boolean; this.discharge$ = this.dischargeService.getObservable('discharges&ap ...

Include the providers after declaring the AppModule

When it comes to Angular 2+, providers are typically registered in the following manner: // Using the @NgModule decorator and its metadata @NgModule({ declarations: [...], imports: [...], providers: [<PROVIDERS GO HERE>], bootstrap: [...] }) ...

What causes the placeholder to be invisible in a select/option when ngModel is used?

While using a select with ngModel to capture the value of the options, I noticed that when I render it, there is no placeholder displayed as shown in the image below: https://i.sstatic.net/fkjOr.png This is the code snippet: <select [value]="sel ...

When users install my npm module, they are not seeing text prediction (intellisense) in their editors

I'm currently focused on developing my package @xatsuuc/startonomy. I'm encountering an issue where Intellisense is not working properly when the package is installed on the user's side. Even though the .d.ts files are visible in node_modul ...

What is the significance of Node.js in partnership with Angular?

What is the specific reason for Node.js being necessary to use Angular? While some argue that it’s not a requirement and is only needed if server-side code is used, the official Angular documentation clearly states the necessity of Node.js in the "Getti ...

Experiencing a 400 bad request error while making a post request in Angular. Any solutions to resolve

I need assistance with my Angular and Django project because I am encountering a 400 bad response error when making a post request. The project workflow is as follows: the user successfully signs up, is then directed to a profile form, and upon submitting ...

The prototype's function doesn't pause for anything, carrying out its duty in a continuous cycle

I have been attempting to enhance the prototype of an object by adding an asynchronous function to be called later on. Here is my approach: const ContractObject = Object; ContractObject.prototype['getBalance'] = async function(userId: number ...

Issue with passing JSON object from Angular2 HTTP post to MVC 6 controller action

In my current project, I am developing an angular 2 application using asp.net MVC6. The issue I am facing is related to Angular2 Http post method calls in the controller action. It works perfectly fine when there are no parameters/properties involved. Howe ...

Can a TypeScript interface inherit from multiple other interfaces simultaneously?

Hello Angular Community, I have a question regarding nesting three interfaces within another interface. Let me explain with some code: I am attempting to integrate the IProject1, IProject2, and IProject3 interfaces into the IAdmin2 interface: Thank you ...

Enhancing keyboard accessibility with the spacebar for radio buttons and check boxes in Angular 2

I am currently working on a form in Angular 2 that includes radio buttons and checkboxes. When tabbing through the fields, they are highlighted properly. However, I am facing an issue with the radio buttons - I want them to be selected when I hit the space ...

MSBUILD encounters numerous JQuery errors when compiling a web project with TypeScript

Currently, I am working on a .net core 3.1 (netcoreapp3.1) razor pages project that includes typescript files and a few javascript files. The project builds perfectly from Visual Studio 2019 (professional) as well as from the command line using MSBuild. H ...