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

The equivalent of ESM for resolving modules using the `createRequire` function with a specified

In the process of developing a JavaScript instrumentation engine, I am currently focused on traversing a source file's Abstract Syntax Tree (AST) and queuing imported modules for instrumentation in a recursive manner. In order to achieve this, it is c ...

Implementing global user authentication state with Zustand in Next.js version 13.4.9

I'm grappling with incorporating zustand into my Next.js 13.4.9 app, specifically for managing global authentication state. Below is the code snippet I have in my application: zustand store: // /src/store/AuthStore.ts import { create } from 'zu ...

Issue with clientHeight not functioning properly with line breaks in Angular 2 application after ngAfterViewInit

I have successfully created a Gridify page in my Angular 2 application using the Gridify library. To initialize it, I've utilized a custom ngAfterViewChecked method: ngAfterViewChecked() { var selector = document.querySelector('.read-grid& ...

Create an interactive and responsive user interface for Object using the Angular framework

After receiving a JSON Object from an API call with multiple string values, I need to create an Interface for this Object in the most efficient way possible. Rather than manually writing an Interface with 100 keys all of type string, is there a quicker a ...

transitioning from angular cli version 1.7 to version 12

Looking for a detailed guide on upgrading from version 1.7 to the latest Angular version (12/11)? I currently have an app running on version 1.7 and couldn't find a step-by-step process here: upgrading angular Would it be safe to assume that the upgr ...

Convert the property that starts with XX from XML to JSON

I am currently working on a function that looks like this request.execute('[someSP].[spSomeSP]', function(err, dataset) { _.map(dataset, function(items) { console.log(items); }); }); When the _.map(...) is executed, it retu ...

Is there a way to switch between showing and hiding all images rather than just hiding them one by one?

Is there a way I can modify my code to create a button that toggles between hiding and showing all images (under the user_upload class), instead of just hiding them? function hidei(id) { $('.user_upload').toggle(); Any suggestions would be grea ...

Cannot establish a connection with Socket.IO

I've encountered an issue with establishing a connection to Socket.IO in my node server. Although the server starts successfully with Socket.IO, I am not seeing any console logs when trying to connect to Socket. this.server.listen(this.port, () => ...

What is the best way to add a new row to an existing CSV file using json2csv in Node.js?

I need to append a new row to an existing CSV file. If the CSV file already exists, I want to add the new row after the last existing row without adding a column header. Here is the code snippet that I have been using: var fields = ['total', &a ...

Is there a way to verify HTML binding prior to setting up an AngularJS directive?

On a page where I utilized a custom select-box directive to display the Month, certain arguments are required by the directive: <custom-select-box id="month" model="month" model-required model-name="month" options="month.value ...

Encountering an issue with Next.js, Typescript, and mongoose when attempting to use `let cached = global.mongoose

I attempted to create a cached mongoose connection for my Next.js + Typescript application, but the code I used was: let cached = global.mongoose; if (!cached) { cached = global.mongoose = { conn: null, promise: null }; } The use of global.mongoose res ...

Failing to verify the presence of specific text within a dropdown menu using Selenium

Previously, I successfully implemented this code, however, the HTML/CSS for the dropdown has since changed and now I am unable to get it to function correctly. Below is the structure for the dropdown code, with specific text highlighted that I am trying t ...

Utilizing Foundation and jQuery in a Next.js web development project

I've been attempting to incorporate Zurb Foundation's scripts into my next js application, but I keep encountering an error message when trying to include the Foundation core. The error I'm seeing is: /Users/alasdair_macrae/Sites/merlin/spa_ ...

Steps to create an if statement using jQuery

.data( "autocomplete" )._renderItem = function( ul, item ) { return $( "<li></li>" ) .data( "item.autocomplete", item ) if ( ( item.parent_term_id == "16" ) ) { .append( "<a>" + (item.child_term ? item.child ...

Tips for keeping several buttons in the spotlight: HTML/CSS/JS

Looking for a solution to keep multiple buttons toggled on? I'm not very familiar with JavaScript, but I know that adding a class on click won't work if there's already a class set. Maybe giving the element an ID could be a possible solution ...

Error encountered with Next.js and Square API: The Fetch API cannot load due to the unsupported URL scheme "webpack-internal"

I encountered an issue while attempting to retrieve stock data from the Square API. injectGlobalHook.js:1648 Fetch API cannot load webpack-internal:///./node_modules/@next/react-dev-overlay/lib/internal/ReactDevOverlay.js. URL scheme "webpack-internal ...

"Unlocking the Potential of ReactJS: A Guide to Setting Focus on Components Once They Become

My code had a <div> with a child component named SocialPostwithCSS, and when onClick was triggered, it would hide the div, set the state to editing: true, and display a <textarea>. I used this.textarea.focus with a ref={(input)=>{this.textar ...

The Child component is unable to render initially due to the Context API being undefined during the first render of the Child component

I'm struggling to ensure that a child component only renders when the Context API state I've set up is fully mounted. The Parent component fetches data from the server and sets the state based on the received information. Initially, I keep gettin ...

Performing an Ajax request to submit a form without the need to reload the page in MVC

I am looking for assistance with submitting a form from an MVC view without refreshing the page. However, it seems that my AJAX code below is not functioning properly: //here is ajax call function AjaxCallAndShowMessage(btnClick) { $('form').s ...

Encountering issues while attempting to execute node-sass using npm

Currently, I'm attempting to execute node-sass using npm. Displayed below is my package.json: { "name": "my-project", "version": "1.0.0", "description": "Website", "main": "index.js", "scripts": { "sass": "node-sass -w scss/ -o dist ...