What is the best way to sort through an array of objects by a specific attribute using Angular?

Here is a component I have:

import { Component, OnInit } from '@angular/core';


@Component({
    selector: 'app-balance',
    templateUrl: './balance.component.html',
    styleUrls: ['./balance.component.scss']
})
export class BalanceComponent implements OnInit {

    advertisers: [
{'advertiser_id': 1, 'name': 'foo'},
{'advertiser_id': 2, 'name': 'bar'},
{'advertiser_id': 3, 'name': 'cat'},

];
    balances: [
{'advertiser_id': 1, 'value': '100'},
{'advertiser_id': 2, 'value': '200'},
{'advertiser_id': 3, 'value': '300'},
{'advertiser_id': 3, 'value': '500'},
];

    constructor() {}
}

In my template, I'm iterating through the balances to display them in a table. I want to show the advertiser's name next to the balance row. So, I attempted the following:

<div class="card mb-3 shadow-sm">
    <table class="table mb-0">
        <tr>
            <th>Advertiser</th>
            <th class="text-right">Outstanding Balance</th>
            <th class="text-center">Invoices</th>
        </tr>
        <tr *ngFor="let balance of balances">
            <td class="align-middle">

                <span ng-repeat="advertiser in advertisers | filter : { advertiser_id : balance.advertiser_id }">{{ advertiser.name}}</span>
            </td>
            <td class="align-middle text-right">{{ balance.value }}</td>
            <td class="text-center">
                <button type="button" class="btn btn-success">New</button>&nbsp;<button type="button" class="btn btn-secondary">Archive</button>
            </td>
        </tr>

    </table>
</div>

But, I encountered this error:

ERROR TypeError: Cannot read property 'name' of undefined

I thought utilizing the 'filter' pipe would solve it, but I am unsure why it isn't working.

Answer №1

Make a pipe.

@Pipe({
   name: 'myFilterPipe'
})
export class MyFilterPipe implements PipeTransform {

    transform(advertisers: any[], advertiser_id: any): any[] {
         return (advertisers || []).filter(advertiser => advertiser.advertiser_id===advertiser_id) 
    }
}

then swap out

<span ng-repeat="advertiser in advertisers | filter : { advertiser_id : balance.advertiser_id }">{{ advertiser.name}}</span>

with

<span *ngFor="let advertiser of advertisers | myFilterPipe: balance.advertiser_id">{{ advertiser.name}}</span>

Alternatively, preprocess data before displaying (much more efficient)

private balances: BehaviorSubject<any[]> = new BehaviorSubject([]); 
private advertisers: BehaviorSubject<any[]> = new BehaviorSubject([]); 

data$: Observable<any[]> = combineLatest(this.balances.asObservable(), this.advertisers.asObservable()).pipe(
    map([balances,advertisers] => {
        return balances.map(balance => {
            balance.advertisers = advertisers.filter(advertiser=>advertiser.advertiser_id===balance.advertiser_id);
            return balance;
        })
    })
)

and then

<tr *ngFor="let balance of data$ | async">
    <td class="align-middle">
        <span *ngFor="let advertiser of balance.advertisers">{{ advertiser.name}}</span>
    </td>
    <td class="align-middle text-right">{{ balance.value }}</td>
    <td class="text-center">
        <button type="button" class="btn btn-success">New</button>&nbsp;<button type="button" class="btn btn-secondary">Archive</button>
    </td>
</tr>

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

Error message: "Unable to locate HTML container when trying to create a child element in am

Whenever I navigate away from this page and then come back, the chart does not load. Instead, it displays an error message saying html container not found at createChild https://i.sstatic.net/Y7jVN.png However, if I refresh the page, the chart will appear ...

Elevate to Babel 7: Unable to access the property 'bindings' of null

I recently made the switch to Babel 7 (upgrading from version 6) using the following commands: npm remove babel-cli npm install --save-dev @babel/cli @babel/core @babel/preset-env This is the content of my .babelrc file: { "presets": ["env"] } After th ...

Refresh the copyright year by syncing with a time server

Not long ago, I found myself needing to update the copyright year on a website. Instead of using JavaScript to get the year from the system time, I began wondering if there was a way to utilize an internet time server for this purpose. I believe that util ...

Explore visuals in the component repository

I am currently working on an Angular 7 component library and am facing some challenges in adding images for buttons and other elements. My project structure is organized as follows: projects components src lib myComponent assets ...

What would you name this particular element?

I want to create a unique slider design but I'm unsure where to begin or how to search for information because I don't know the correct terminology. Does this type of slider have a specific name? I heard about Marquee, but that seems like someth ...

Create a soft focus on the background sans any filters

I am in the process of developing a website and have implemented code to blur out the background: CSS #background{ background: url(img/bg.jpg) no-repeat center center fixed; -webkit-background-size: cover; -moz-background-size: cover; -o ...

Restart Response Feature

I have managed to reset all the radio buttons, but I'm struggling with resetting the message that appears after giving the correct answer. Any assistance would be appreciated. HTML <button id="resetButton" type="button" onclick="resetAns()">Re ...

Guide on filling out multiple forms with just one form

I am currently working on creating an online application where users can fill out the contact forms on my two other websites, located at and , using the form on my third website at . Essentially, when a user submits the form on , it should automatically ...

Adding a PNG icon to a label in JavaScript: A step-by-step guide

How can I add a png icon alongside the label for Yourself? <div class="ui-grid-a" style="display: inline"> <label class="text-light ui-block-a">Post as: </label> <label class="link toggle-post ui-block-b" > ...

How can I hide a div using Ajax and show success in the following div?

I'm utilizing ajax to implement search functionality onkeyup. The goal is to display all results if the textbox is empty, but when the textbox contains text, only show results that match. <input type="text" onkeyup="searchme()" id="search_id" /&g ...

Persist changes to array even after refreshing the page

Currently, I am utilizing Angular 2 (Typescript) to code my webpage, which features various forms with inputs. Upon submitting these forms, they each trigger a function that adds a new instance of an object based on the inputs to an array. This array is th ...

Step-by-step guide for embedding a Big Commerce website into an iframe

Can a website be opened inside an iframe? If not, is it possible to display a message like 'page not found' or 'this website does not allow data fetching in iframes'? <!DOCTYPE html> <html> <body> <h1>Using the ...

Triggering a success message when clicked using JavaScript

<div id="success"> <button class="btn btn-primary btn-xl" type="submit" id="btnShow">Send</button> </div> As a beginner in JavaScript, I am struggling to write the code for displaying a success alert upon clicking the button. ...

Exploring the Depths of Scope Hierarchy in AngularJS

Upon inspecting the _proto__ property of an object I created, it is evident that it has been inherited from Object. https://i.stack.imgur.com/hcEhs.png Further exploration reveals that when a new object is created and inherits the obj object, the inherit ...

Mongoose: Insert a new item into an array of objects within an object property

I need help adding an element to an existing array within an object field in my mongoose "Utilisateur" schema. This is what my schema looks like: https://i.sstatic.net/xv69M.png The goal is to insert a new element into the "lien_vers" array using the foll ...

Is it possible to specify the timing for executing Typescript decorators?

One issue I've encountered is that when I define a parameterized decorator for a method, the decorator runs before the method itself. Ideally, I'd like the decorator to run after the method has been called. function fooDecorator(value: boolean) ...

Local Bootstrap notifications functioning correctly, but failing to display on the server

I successfully set up notifications in a localhost application, and they were functioning perfectly. However, after uploading to the server, the notifications stopped displaying without any changes being made. The application consists of two main files: ...

How about inputting some text into a field?

Below is the code snippet for your reference: <div class="col-xs-12 col-sm-9"> <input id="Shipping_FirstName" name="firstname" ng-model="userOrder.Shipping.FirstName" type="text" class="form-control nsg-form--input ng-pristine ng-untouc ...

While developing an exam portal with Angular and Spring Boot, I encountered an issue when trying to incorporate a name field as [name]

Component.html <div class="bootstrap-wrapper" *ngIf="!isSubmit"> <div class="container-fluid"> <div class="row"> <div class="col-md-2"> <!- ...

Unable to navigate between components in Angular

Currently, I am attempting to toggle between two components within my Angular application. My goal is to have a preloader displayed while the page is loading and switch to the main component once the page has fully loaded. Initially, the preloader variable ...