How to filter an array within an array using Angular

Currently, I am developing a project in Angular 9 and I have encountered a challenge regarding filtering an array based on another nested array within each object. To illustrate my issue, here is a sample of the array:

const products = [
  {
      name: 'Product 1',
      origins: [
          { quantity: 1, name: 'Pack 1' },
          { quantity: 1, name: 'Pack 2' },
      ]
  },
  {
      name: 'Product 2',
      origins: [
          { quantity: 1, name: 'Pack 1' },
          { quantity: 1, name: 'Pack 2' },
      ]
  },
  {
     name: 'Product 3',
     origins: [
          { quantity: 1, name: 'Inventory' },
          { quantity: 1, name: 'Pack 5' },
     ]
  }
]

I need to implement a filter functionality that can search for matches based on the product name or any origin's name.

For instance, if the user types "2", the filtered array should look like this:

products = [
  {
      name: 'Product 1',
      origins: [
          { quantity: 1, name: 'Pack 2' },
      ]
  },
  {
      name: 'Product 2',
      origins: [
          { quantity: 1, name: 'Pack 2' },
      ]
  }
]

This outcome demonstrates how the character "2" appears in both the name of the origins and the product itself (e.g., Product 1 and Product 2).

I have attempted various strategies to achieve this without modifying the original array, especially when implementing it within a pipe.

<input type="text" [(ngModel)]="searchtext">
<div *ngFor="let p of (saleProducts | filter : searchtext); let i = index">
    {{ p.name }}
    <div *ngIf="p.origins.length > 0">
        <div *ngFor="let o of p.origins">
            {{ o.name }}
        </div>
    </div>
</div>

What would be the most efficient and straightforward approach to create a non-destructive filtering mechanism using a pipe in this scenario?

Answer №1

Here is a custom pipe implementation in Angular that filters data based on a default key "origins":

import { Pipe, PipeTransform } from '@angular/core';

@Pipe({
  name: 'filter'
})
export class FilterPipe implements PipeTransform {

  transform(value: any[], searchName: string, key = 'origins'): any[] {
    const filteredData = [];
    
    value.forEach(item => {
      const matches = item[key].filter(({ name }) => name === searchName);
      
      if (matches.length) {
        filteredData.push({ ...item, [key]: matches });
      }
    });
    
    return filteredData;
  }
}

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

Reserve memory for an array of fixed-size arrays dynamically

After reading numerous posts on this topic, it seems that my issue is a bit more specific. I am attempting to allocate a dynamic 2D array. Due to restrictions in the existing code, I need to use a typedef for a static array. However, now I need to tempora ...

The Angular Material Table experienced a collapse when trying to render over 20 columns simultaneously

Currently, I am experiencing an issue in Angular Version 5 where the Angular Material Table collapses when rendering more than 20 columns. Here is a snapshot of what my table looks like: https://i.stack.imgur.com/MXfvQ.png https://i.stack.imgur.com/XHWgq ...

What is the reason the 'Add' type does not meet the 'number' constraint?

I experimented with type gymnastics using Typescript, focusing on implementing mathematical operations with numeric literals. First, I created the BuildArray type: type BuildArray< Length extends number, Ele = unknown, Arr extends unknown ...

Angular component experiencing an issue with an upgraded Angular service: encountering an Undefined error

I've been working on upgrading an AngularJS app to Angular, but I've hit a roadblock. I'm trying to configure Angular to handle the home route, but it's not working. The issue seems to stem from the upgraded service. Interestingly, whe ...

Generating and setting an object property in TypeScript at runtime

In my code, I have defined an interface as follows: export interface OurHistory { ourHistory?: object; step1?:object; step2?:object; } Within the HistoryComponent class, I am doing the following: export class HistoryComponent implements OnInit, On ...

Creating a TypeScript class that includes all the attributes of a pre-existing object type

One technique I frequently use in TypeScript involves transforming a plain JSON object definition into a class during runtime. Here's an example: export type LessonDef = { id: string title: string slug: string shortdesc: string explanation: ...

Including an extra day in an array to ensure proper date formatting in Angular

Within my Angular project, there exists an array structured as follows: Thali : [ {"date":"2017-04-09T18:30:00.000Z","isHoliday":"100"}, {"date":"2017-04-10T18:30:00.000Z","isHoliday":"101"} ] Upon selecting a date from the date picker, such as the f ...

Issues with JavaScript Array Splice Function

var cache = []; cache[0] = "0"; cache[1] = "1"; cache[2] = "2"; cache[3] = "3"; cache[4] = "4"; cache["r"] = "r"; console.log(cache.length); for(key in cache){ if(isNaN(key))continue; else cache.splice(key,1); // The functionality of cache.splice(k ...

Error: The file type you are trying to upload is not supported

my document-upload.service.ts private uploadFile(file: File) { let formData: FormData = new FormData(); formData.append('uploadFile', file, file.name); let headers = new HttpHeaders({'Content-Type': 'multip ...

How can we implement ngxs async observable interpolation in a component.ts file instead of the HTML?

When working on my Angular app's HTML, I successfully displayed the "title" from a variable using the following code: The following code worked fine in my component.html file: <input matInput value="{{ (app$ | async).myTitle.match('title: &a ...

Split a string using two different delimiters to generate a multidimensional array

I have a string with specific data elements: 01;Tommy;32;Coder&&02;Annie;20;Seller I am looking to format it into an array like this: array (size=2) 0 => array (size=4) 0 => string '01' (length=2) 1 => string 'To ...

Store the Ajax JQuery selector within an array for safekeeping

I am completely new to working with Ajax and would appreciate some assistance in storing data from an Ajax request into an array. I have browsed through various solutions on this forum, but so far, I have been unable to resolve my issue. The Ajax respons ...

Steps for preventing text manipulation in ng2-ace-editorWould you like to restrict users from copying, pasting

How can I prevent users from copying, pasting, and dropping text in ng2-ace-editor? https://github.com/fxmontigny/ng2-ace-editor is the library I implemented in my Angular 5 application. ...

Tips for preventing the ngbTypeahead input field from automatically opening when focused until all data is fully mapped

When clicking on the input field, I want the typeahead feature to display the first 5 results. I have created a solution based on the ngbTypeahead documentation. app.component.html <div class="form-group g-0 mb-3"> <input id="typ ...

Styling the pseudo element ::part() on an ion-modal can be customized based on certain conditions

Looking for a solution regarding an ion-modal with specific CSS settings? I previously had the following CSS: ion-modal::part(content) { width: 300px; height: 480px; } Now, I need to adjust the height based on conditions: if A, the height should be lo ...

Encountered a Solana Error while handling Instruction 2: custom program error with code 0x1000078

While attempting to create an AMM Pool using the 'ammCreatePool.ts' script from the raydium-sdk repository, I encountered the following error message. I executed the script directly with ts-node src/ammCreatePool.ts and made modifications so that ...

Verifying the format of an object received from an HTTP service using a TypeScript interface

Ensuring that the structure of the http JSON response aligns with a typescript interface/type is crucial for our javascript integration tests against the backend. Take, for example, our CurrentUser interface: export interface CurrentUser { id: number; ...

The requirement of the second parameter being optional or required will depend on the value of the first

Is there a way to make the second parameter of my function optional or required based on the value of the first parameter? Here's an example code snippet: enum Endpoint { USERS = '/users/:userId', ORDERS = '/orders' } typ ...

Ways to display collapse content and hide it again with a click

Working on my Angular 2 project, I have created collapsible tabs. When a button is clicked, the corresponding tab collapses, and I want it to be hidden if the same button is clicked again. However, the tabs are generated dynamically or through looping: Th ...

Child component in Angular not receiving updated variable values when being called from parent component

Struggling with dynamically updating the style of an element. I've added margins on top of an image by creating a child component to handle it. I invoke a function on the child component that calculates the margins and sets a variable. This is how t ...