What is the best way to sort through this complex array of nested objects in Typescript/Angular?

tableData consists of an array containing PDO objects. Each PDO object may have zero or more advocacy (pdo_advocacies), and each advocacy can contain zero or more programs (pdo_programs). For example:

// Array of PDO object
[
    {
        id: 1,
        pdo_currency: "PHP",
        name: "Gemango",
        abbreviation: "Gemango",
        dt_founded: "May. 02, 2024",
        dt_created_at: "Jan. 01, 1970",
    // Array of PDO advocacies
        pdo_advocacies: [
            {
                id: 1,
                advocacy: "PDO Operations",
                pdo_id: 1,
        // Array of PDO programs
                pdo_programs: [
                    {
                        id: 6,
                        program: "PDO Budget",
                        pdo_advocacy_id: 1,
                        pdo_id: 1,
                        admin_beneficiary_category_id: 2,
                        beneficiary_category: {
                            id: 2,
                            name: "elders",
                        },
                        program_priority: {
                            id: 295,
                            name: "High",
                        },
                        program_category: null,
                        proposed_date: null,
                        funding_needs: "20000.00",
                        admin_beneficiary_category: {
                            id: 2,
                            category: "Children",
                        },
                        pdo_program_locations: [
                            {
                                id: 6,
                                pdo_program_id: 6,
                                location: {
                                    id: 3,
                                    name: "CEBU CITY, CEBU, PHILIPPINES",
                                },
                                funding_needs_location: "0.00",
                                unit_of_item: null,
                                num_of_items: 0,
                                num_of_beneficiaries: 0,
                            },
                        ],
                    },
                ],
            },
            {
                id: 2,
                advocacy: "Unrestricted",
                pdo_id: 1,
                pdo_programs: [
                    {
                        id: 1,
                        program: "Unrestricted Funds",
                        pdo_advocacy_id: 2,
                        pdo_id: 1,
                        admin_beneficiary_category_id: null,
                        beneficiary_category: null,
                        program_priority: null,
                        program_category: null,
                        proposed_date: null,
                        funding_needs: "0.00",
                        admin_beneficiary_category: null,
                        pdo_program_locations: [
                            {
                                id: 1,
                                pdo_program_id: 1,
                                location: {
                                    id: 1,
                                    name: "Main",
                                },
                                funding_needs_location: "0.00",
                                unit_of_item: null,
                                num_of_items: 0,
                                num_of_beneficiaries: 0,
                            },
                        ],
                    },
                ],
            },
        ],
    },
];

selectedOptions

[
    {
        "id": 2,
        "name": "Children"
    }
]

This code is designed to filter and return only the PDO, advocacy, and programs that have an admin_beneficiary_category.category value of "Children".

Filter Implementation

        this.filteredTableData = this.tableData.filter((pdo) => {
          return pdo.pdo_advocacies.some((advocacy) => {
            return advocacy.pdo_programs.some((program) => {
              return selectedOptions.some((option) => {
                // Check if admin_beneficiary_category is null or undefined
                if (program.admin_beneficiary_category === null || program.admin_beneficiary_category === undefined) {
                  // Check if the option name is 'null'
                  return option.name === 'null';
                }
                // Compare the program category name with the selected option name
                return option.name === program.admin_beneficiary_category.category;
              });              
            });
          });
        });

Actual Output

[...]

Expected Output:

[...]

Complete Code: https://stackblitz.com/edit/stackblitz-starters-azu5d2?file=src%2Fmain.ts

Answer №1

After reading the insightful tips provided in this Stack Overflow post, everything finally clicked for me.

The key takeaway is to utilize a blend of nested map and spread operator rather than nesting some and filtering solely at the deepest level object.

        Upon implementing the solution, I utilized the following code snippet:
          .map(pdo => {
            // Filter pdo_advocacies
            const filteredAdvocacies = pdo.pdo_advocacies
              .map(advocacy => {
                // Filtering pdo_programs based on certain conditions
                const filteredPrograms = advocacy.pdo_programs.filter(program => {
                  return selectedOptions.some(option => {
                    if (!program.admin_beneficiary_category) {
                      return option.name === 'null';
                    }
                    return option.name === program.admin_beneficiary_category.category;
                  });
                });
                // Return only the advocacies with filtered programs
                return {
                  ...advocacy,
                  pdo_programs: filteredPrograms,
                };
              })
              .filter(advocacy => advocacy.pdo_programs.length > 0); 

            // Returning pdo objects only if they have filtered advocacies
            return {
              ...pdo,
              pdo_advocacies: filteredAdvocacies,
            };
          })
          .filter(pdo => pdo.pdo_advocacies.length > 0);

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

Retrieving JSON information from asynchronous JavaScript and XML (AJAX)

I am struggling with making a URL that contains JSON Data work properly. The issue lies in the data field - I am unsure of what to input here as it is currently undefined. My goal is to store an array of the JSON data received from the ajax request. What ...

Is it possible to utilize Vue's splice method within a forEach loop in order to delete multiple elements at

I am currently working on an image grid in array form. I am trying to implement a multi-deletion functionality. When a checkbox for each image in the grid is checked, I store the selected image's index in an array called selectedImages. Upon clickin ...

The Quirks of jQuery's .load() Method

On my website, I am incorporating a basic jQuery script to load content from one part of a webpage into the 'display container' on the same page. The content being loaded consists of multiple divs enclosed within an outer <div> that is hid ...

Having trouble executing "npm install" following the clone from GitHub in React

After cloning a repository from GitHub, I attempted to run "npm install" but encountered the following error: Since the project is still in development, should I install or add anything else to successfully run it? ...

Node.js allows for keeping pipe and sockets open even after streaming an HTTP response

My current challenge involves streaming data from an HTTP response to a cloud storage provider within an internal service. const response = await request<Readable>({ headers: httpOpts?.headers, data: httpOpts?.data, url, method, responseTyp ...

What could be causing my scene to fail to render?

I'm attempting to adapt this particular example into CoffeeScript. Below is a snippet of my code: class Example width: 640 height: 480 constructor: -> @camera = new THREE.PerspectiveCamera 45, @width/@height, 10000 @cam ...

What could be the reason for encountering the 'SyntaxError: Cannot use import statement outside a module' when trying to utilize the cloudinary module?

I am facing an issue while trying to utilize the Cloudinary module for resizing an image. Below is the code snippet I have: import cloudinary from 'cloudinary'; var cl = new cloudinary.Cloudinary({ cloud_name: "username", secure: true } ...

Why does the Leaflet map appear inconsistently?

It's baffling that Firefox 24.0 and the latest Chrome are both failing to load my Leaflet map, but surprisingly, it works perfectly on Safari on my iPhone. Quite an interesting dilemma. This is my initial attempt at using Leaflet and Bootstrap...ever ...

Angular Service Fails to Execute Upon Initial Loading

In my current project, I am utilizing Angular 9.0.7 with a Node.js (Express) backend and an Angular frontend. The issue I'm facing is that the service function responsible for fetching data from the backend is not being invoked on the initial page lo ...

Tips on sorting a FileList object selected by a directory picker in JavaScript/TypeScript

I need to filter or eliminate certain files from a FileList object that I obtained from a directory chooser. <input type="file" accept="image/*" webkitdirectory directory multiple> Within my .ts file: public fileChangeListener($event: any) { let ...

Using Cordova for mobile applications to play local video files

Our iOS app, developed using PhoneGap / Cordova 4.3.0, loads an external website directly utilizing <content src="http://example.com/foo" /> in the config.xml file. All functionality resides within this website, eliminating the need for local HTML or ...

What are the steps to generate two unique instances from a single class?

Is there a way to output two instances of the class Cat : Skitty, 9 years and Pixel, 6 years, in the console? (() => { class Cat { constructor(name, age) { this.name = name; this.age = age; } } docume ...

Enhancing a UMD module definition with TypeScript 2: A step-by-step guide

Currently, I am in the process of creating TypeScript definition files for two libraries that are meant to be used with the new @types approach. Both libraries adhere to the UMD pattern, allowing them to be consumed either as modules or by referencing them ...

Tips for generating an ecosystem.json file for a node.js express app with pm2 that launches with npm start command

I am looking to utilize pm2 for my node.js express app. Although I can successfully start the server using npm start, I want to set it up in the ecosystem.json file so that I can manage it with pm2 and run it in cluster mode. One thing to note is that I c ...

Best practices for incorporating CSS and JS files into an Angular deployment

I am currently in the process of integrating an Admin Template that I previously used in a traditional PHP application into a new Angular project. <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <link rel= ...

Effortless method to handle package.json configurations

Is there a better approach for seamlessly transitioning between using npm link and git, or another solution that caters well to both front end and back end developers? The dilemma I'm facing revolves around developing a website that utilizes multiple ...

Translate array into object with correct data types (type-specific method)

Welcome In our project, we have implemented attributes support where each attribute acts as a class. These attributes include information on type, optionality, and name. Instead of creating an interface for every entity, my goal is to automate this proces ...

Reactivate IntelliJ IDEA's notification for running npm install even if you have previously selected "do not show again" option

One of the great features in Intellij IDEA is that it prompts you with a notification when the package.json has been changed, asking if it should run npm install, or whichever package manager you use. I have enjoyed using this feature for many years. Howe ...

What is the best way to ensure that the circle is perfectly centered inside the box?

Currently delving into the world of game programming, I've been struggling with this exercise. I can't seem to figure out why the circle won't stop in the center of the box within the update function. What am I missing? var canvas = documen ...

Adjust the hue of a picture rendered on an HTML5 canvas element

Looking at this image, I am wondering: What is the best way to change the entire color of this image to a custom RGB value? Essentially, if I have a grayscale image, how can I convert it back to color by specifying any RGB value? ...