Displaying grouped arrays efficiently in Angular

I have received data from an API in the form of an array with objects structured like so:

[
  {"desc":"a", "menu": 1},{"desc":"b", "menu": 2},{"desc":"c", "menu": 1}, 
  {"desc":"d", "menu": 3},{"desc":"e", "menu": 3},{"desc":"f", "menu": 2}, 
  {"desc":"g", "menu": 1},{"desc":"g", "menu": 1},{"desc":"g", "menu": 4}, 
  {"desc":"g", "menu": 4},{"desc":"g", "menu": 4}
]

I want to display these objects using *ngFor, grouped by their "menu" property, and with a corresponding label for each group as follows:

Menu 1

{all objects with menu 1}

Menu 2

{all objects with menu 2}

Menu 3

{all objects with menu 3}

To achieve this, I plan to use *ngFor and set up logic to create labels for each menu group. Here is a rough outline of how I would approach it:

*ngFor="let object of objects; let currentMenu = 0"
     if currentMenu !== object.menu
           currentMenu === object.menu
       CREATE LABEL

If you have any suggestions on how to implement this effectively in actual code, please share them!

Answer №1

To improve the efficiency, I suggest grouping the data before utilizing the *ngFor directive. Here is a possible solution:


function groupBy(array, key) {
    return array.reduce((acc, current) => {
        (acc[current[key]] = acc[current[key]] || []).push(current);
        return acc; 
      }, {});
}

function toArray(obj) {
    return Object.keys(obj).map(key => obj[key]);
}

const data = [
  {"desc":"a", "menu": 1},{"desc":"b", "menu": 2},{"desc":"c", "menu": 1}, 
  {"desc":"d", "menu": 3},{"desc":"e", "menu": 3},{"desc":"f", "menu": 2}, 
  {"desc":"g", "menu": 1},{"desc":"g", "menu": 1},{"desc":"g", "menu": 4}, 
  {"desc":"g", "menu": 4},{"desc":"g", "menu": 4}
]

const groupedData = groupBy(data, "menu");

Then, in your template, you can utilize the grouped data like this:


<group *ngFor="let group of groupedData">
  <menu *ngFor="let item of group">
    <label>{{item.desc}}</label>
  </menu>
</group>

Answer №2

You can implement a solution like this:

ngOnInit(){
    var groups = new Set(this.array.map(item => item.menu))
    this.result = [];
    groups.forEach(g => 
      this.result.push({
        menu: g, 
        values: this.array.filter(i => i.menu === g)
      }
    ))
  }

This code snippet shows how to render the data in HTML:

<p>
    Start editing and see the magic happen :)
</p>
<div *ngFor="let item of result" border="1">
    <table>
        <tr>
            <th>Desc</th>
            <th>Menu</th>
        </tr>
        <ng-container>
            <tr>
                <td colspan="2">{{item.menu}}</td>
            </tr>
            <tr *ngFor="let value of item.values">
                <td>{{value.desc}}</td>
            </tr>
        </ng-container>
    </table>
    <div>

Feel free to check out the stackblitz I created. https://stackblitz.com/edit/angular-4ekz4n

Happy coding! :)

Answer №3

Learn how to write import statements within an Angular component

import { of } from 'rxjs';
import { groupBy, mergeMap } from 'rxjs/operators';

Next, add the following code snippet inside the ngOnInit() method:

ngOnInit():void{
on(
    {id: 1, name: 'JavaScript'},
    {id: 2, name: 'Parcel'},
    {id: 2, name: 'webpack'},
    {id: 1, name: 'TypeScript'},
    {id: 3, name: 'TSLint'}
).pipe(groupBy(a=>a.id)),
 mergeMap((group$) => group$.pipe(reduce((acc, cur) => [...acc, cur], []))),
)
.subscribe(p => console.log(p));

//The expected output will be as follows:

[ { id: 1, name: 'JavaScript'},
{ id: 1, name: 'TypeScript'} ]
[ { id: 2, name: 'Parcel'},
  { id: 2, name: 'webpack'} ]
[ { id: 3, name: 'TSLint'} ]

For further details, visit rxJS operators for groupBy

Answer №4

The first step is to restructure the current array to match the format below:

[
  {
    category: 1,
    items: ["a", "b"]
  },
  {
    category: 2,
    items: ["a1", "b1", "c1", "d1"]
  }
]

You can achieve this by iterating through the current array in the component's TypeScript file and organizing it as demonstrated in the example above.

Once you have updated the array, you can use it with *ngFor in the HTML to display the data.

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

Opting In to Share Telemetry Data in Angular 8

Can someone help me understand how to enable the telemetry data sharing feature in Angular 8? I've done my research on the new features of Angular 8 and came across the option to opt-in for sharing usage data, but I'm unsure about where to find ...

Ensuring Uniform Data Types Across Objects (Using Typescript)

After much trial and error, I have finally reached this point where everything seems to be working perfectly. function test<types extends Record<string,any>>(dict: dictionary<types>){} type dictionary<types extends Record<string, a ...

Linking events together to fetch interconnected information

When loading an employee in my resolver, the employee returns a list of town's ids. My goal is to load all the towns from this id list within the same resolver without returning the list of towns, but instead returning the employee object. The loaded ...

Is the ng-selector in Angular2 not sorting items alphabetically as expected?

This code snippet demonstrates the use of ng-selector in an .html file <ng-selector name="company" [(ngModel)]="company_selected" [formControl]="loanApplyForm.controls['company']" ...

Typescript - Defining string value interfaces

I have a property that can only be assigned one of four specific strings. Currently, I am using a simple | to define these options. However, I want to reuse these types in other parts of my code. How can I create an interface that includes just these 4 va ...

Tips on fixing the "TypeError: Cannot read properties of undefined (reading 'lookup')" error message that occurs when running npm install

After successfully running npm install on a freshly cloned Angular project, I encountered an error with the node_modules when trying to launch the application using ng s. Could this issue be related to the version of Node.js being used? \node_modules& ...

Navigating to a Child Module within a Parent Module in Angular 2 Release Candidate 5

I am currently in the process of updating an application I have been working on to the latest Angular 2 release candidate. As part of this upgrade, I am utilizing the NgModule spec and transitioning all parts of my application into modules. So far, the tra ...

Using [(ngModel)] on a field within an object that is nested inside another object

I am facing a challenge as I attempt something that may or may not be feasible. Within an Angular form, I have an object structured like this: export class NewUserRegisterModelDTO{ userData:UserDetailModelDTO; roles:RoleModelDTO[]; ownerData:O ...

Custom component not rendering expected CSS style

I have successfully developed a custom web component without using any framework. I then proceeded to populate it with content from a template tag. Although I was able to manipulate the content using JavaScript, I encountered difficulties when trying to m ...

The "initialized" event in angular2-tree-component fires prior to the data being loaded

Utilizing the angular2-tree-component, my goal is to display an already expanded tree. According to Angular docs, the initialized event should be used for expanding the tree after the data has been received: This event triggers after the tree model has ...

Guide on setting up multiple Axios instances in NestJS

I'm in the process of migrating an existing Express application to NestJS. Currently, I have a configuration file where I define multiple axios instances for each microservice: export const writeModelApi = axios.create({ baseURL: getWriteModelApiUrl ...

Is it not possible to utilize inline "if" statements in conjunction with useEffect within a functional React component?

I'm currently working on integrating Okta's React SDK into a TypeScript-based application using functional components instead of class-based ones. My main challenge lies in rendering a part of the app's menu based on the user's authenti ...

Unable to retrieve component name using React.Children

While working with react in the nextjs framework, I attempted to create my own dropdown component structured as follows: <Dropdown> <DropdownToggle>Action</DropdownToggle> <DropdownMenu> <DropdownItem>Menu 1</Dr ...

Listening for Angular 2 router events

How can I detect state changes in Angular 2 router? In Angular 1.x, I used the following event: $rootScope.$on('$stateChangeStart', function(event,toState,toParams,fromState,fromParams, options){ ... }) In Angular 2, using the window.addEv ...

React: Using useState and useEffect to dynamically gather a real-time collection of 10 items

When I type a keystroke, I want to retrieve 10 usernames. Currently, I only get a username back if it exactly matches a username in the jsonplaceholder list. For example, if I type "Karia", nothing shows up until I type "Karianne". What I'm looking f ...

Unable to assign to 'disabled' as it is not recognized as a valid attribute for 'app-button'

How to link the disabled property with my button component? I attempted to add 'disabled' to the HTML file where it should be recognized as an input in the button component (similar to how color and font color are recognized as inputs) ... but ...

The Heart of the Publisher-Subscriber Design Paradigm

After reading various online articles on the Publisher-Subscriber pattern, I have found that many include unnecessary domain-specific components or unreliable information inconsistent with OOP standards. I am seeking the most basic and abstract explanatio ...

Creating formGroups dynamically for each object in an array and then updating the values with the object data

What I am aiming to accomplish: My goal is to dynamically generate a new formGroup for each recipe received from the backend (stored in this.selectedRecipe.ingredients) and then update the value of each formControl within the newly created formGroup with t ...

What are the steps to resolve the error message "Make sure the component is enclosed within a <Provider>" while using Next 14 with Redux Toolkit?

I've been struggling to get Next.js 14 to work with Redux Provider. I followed all the guidelines on the Redux official documentation here, but I keep encountering this error: Error: could not find react-redux context value; please ensure the compo ...

Hover Effect for 3D Images

I recently came across an interesting 3D Hover Image Effect that I wanted to implement - https://codepen.io/kw7oe/pen/mPeepv. After going through various tutorials and guides, I decided to try styling a component with Materials UI and apply CSS in a differ ...