Arrangement of items in Angular 2 array

Received a JSON response structured like this

JSON response

"Terms": [
            {
                  "Help": "Terms",
                "EventType": "Success",
                "Srno": 1,
                "Heading": "Discount Condition",
                "TermsDesc": "50 % Discount on 1st Cab Ride"
            },
            {
                "Help": "Terms",
                "EventType": "Success",
                "Srno": 2,
                "Heading": "Discount Condition",
                "TermsDesc": "20% Discount on Nights more than 8"
            },
            {
                "Help": "Terms",
                "EventType": "Success",
                "Srno": 1,
                "Heading": "Stay Condition",
                "TermsDesc": "No More than 10% Discount on Less than 4 Nights Stay"
            },
            {
                "Help": "Terms",
                "EventType": "Success",
                "Srno": 2,
                "Heading": "Stay Condition",
                "TermsDesc": "20% Discount on Nights more than 8"
            },
            {
                "Help": "Terms",
                "EventType": "Success",
                "Srno": 3,
                "Heading": "Discount Condition",
                "TermsDesc": "No More than 10% Discount on Less than 4 Nights Stay"
            }
        ],

The goal is to categorize the terms by Heading. Terms with the same Heading should be grouped together, for example: Discount Condition and Stay Condition from the original response

Discount Condition

  • "50 % Discount on 1st Cab Ride"
  • "20% Discount on Nights more than 8"
  • "condition 3"

Stay Condition

  • "50 % Discount on 1st Cab Ride"
  • "20% Discount on Nights more than 8"
  • "condition 3"

The function component where the response is processed:

 getTerms(){
    this.quoteService.getTerms()
    .subscribe(
      terms => {
        this.terms = terms.resultData.Terms;
        this.notes = terms.resultData.ImpNotes;
        this.exclusions = terms.resultData.Exclusions;
        var arr=[];
        var strHeading;
        var title;
        var temp = 0;
        var listing = [];
        for(let i=0;i<this.terms.length;i++) {
          strHeading=this.terms[i].Heading;
          title=this.terms[i].TermsAndConditionsDesc;
          if(!this.uniqTerm[temp]){
            this.uniqTerm[temp] = [];
          }
          if (arr.indexOf(strHeading) !== -1) {
            this.uniqTerm[temp].push({"header":strHeading});
          } 
          else {
               arr.push(strHeading);               
               this.uniqTerm[temp].push({"header":strHeading});               
               listing.push({"title":title});
               this.uniqTerm[temp].push({"title":title});
               temp++;                 
          }
      },
      response => {
        if (response.status == 404) {
        }
      });
  }

How can I format an Array that can be used in *ngFor?

I assume it would need to look something like this

[0]:object
     Heading:"Discount Condition"
     TermsDesc: object
                term: Term1 
                term: Term2

[1]:object
     Heading:"Stay Condition"
     TermsDesc: object
                term: Term1 
                term: Term2

However, I am unsure of how to achieve this using Angular 2. Any assistance or alternative suggestions would be greatly appreciated.

Thank you

Answer №1

To harness the power of the linq-es2015 library, follow these steps:

import { asEnumerable } from 'linq-es2015';

class Term
{
    public Help: string;
    public EventType: string;
    public Srno: number;
    public Heading: string;
    public TermsDesc: string;
}

//within a component
this.terms: Term[];
this.result = asEnumerable(this.terms).GroupBy(x => x.Heading, x => x, (key, b) => { return { Heading: key, TermsDesc: asEnumerable(b).ToArray() } }).ToArray();

//template
<ul>
   <li *ngFor="let term of result">
       {{term.Heading}}
       <ul>
           <li *ngFor="let item of term.TermsDesc">{{item.TermsDesc}}</li>
       </ul>
   </li>
</ul>

Answer №2

After some investigation, I was able to find the solution. Although Slava Utesinov's answer also works, it requires the installation of linq-es2015.

By using the code snippet below, I successfully grouped the objects based on their headings:
const groupedObj = this.terms.reduce((prev, cur)=> {
    if(!prev[cur["Heading"]]) {
        prev[cur["Heading"]] = [cur];
    } else {
        prev[cur["Heading"]].push(cur);
    }
    return prev;
}, {});
this.TermCons = Object.keys(groupedObj)
.map(Heading => ({ Heading, TermsDesc: groupedObj[Heading] }));

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

Generate a new data type based on the value of a single attribute within a collection of objects

Is there a way to extract a specific property of a combined type and generate a new type from it? Consider the following example: type Actions = | { type: "ADD_COLUMN"; newColumnIndex: number; column: SelectorColumnData; } | { type: ...

Potential issue detected in TypeScript relating to the JQuery.html() method

For example: let $div = $("div"); let $p = $("p"); $div.html($p); This is producing the following error message: Supplied parameters do not match any signature of call target. UPDATE: In plain JavaScript/jQuery, the code is working. An equivalent (in f ...

Limiting the use of TypeScript ambient declarations to designated files such as those with the extension *.spec.ts

In my Jest setupTests file, I define several global identifiers such as "global.sinon = sinon". However, when typing these in ambient declarations, they apply to all files, not just the *.spec.ts files where the setupTests file is included. In the past, ...

Setting property values in Typescript by initializing them from other properties when reading objects from a subscription response

I have created a basic class structure export class SampleObj{ item1: string; item2: string; item3: string; } I am fetching data from the backend and populating this class using HttpClient: this.httpClient.get<SampleObj[]>(`backendUrl`).subscr ...

Encountering a TypeScript error in Vue 3 when trying to assign a type of '($event: any) => void' to an event listener

Snippet of component code: <h2 @click="handleEvent(post.id)">{{ post.title }}</h2> function handleEvent(id: number) { router.push("/post/" + id); } Error message in TypeScript: Type '($event: any) => void' i ...

Typescript is unable to locate the .d.ts files

Working on a personal project and came across a library called merge-graphql-schemas. Since the module lacks its own typings, I created a file at src/types/merge-graphql-schemas.d.ts In merge-graphql-schemas.d.ts, I added: declare module "merge-graphql-s ...

Showing the attributes of the chosen items within an array using Angular

I am attempting to showcase the ID of the chosen items from the employee array, which is in a dropdown list. export const employees = [ {index:1,'name':"Josh",'id':"102A"}, {index:2,'name':"Sam",'id':"598A"}, {ind ...

Transferring data from an Angular 2 component to a service

I am trying to pass data from an Angular component to a service and utilize the service's methods to manipulate it. Here is an example: class SomeComponent { public info: Array<any> = MyData; constructor(private myService: TablePag ...

Encountering difficulty invoking a component method from d3's call() function

My current setup involves using D3 to drag and drop links in the following manner: .call(d3.drag() .on("start", linkDragStart) .on("drag", linkDragging) .on("end", linkDragEnd)); Recently, I decided to extract this functionality into a separate met ...

Switch from flexbox layout to begin on the next column within the same row

I am attempting to create a CSS layout where, after a specific element like :nth-child(6), the elements will break and form a separate column within the same row. The parent element should split into 2 columns after every 6th element in the same row, then ...

Error in Redirecting to Localhost

Recently, I developed an Angular App that interacts with the MS Graph API using MSAL. Initially, everything worked smoothly when running "ng serve" in Angular CLI. However, I encountered a problem when I packaged this Angular App with electron to deploy i ...

Excluding certain source files in Typescript's tsconfig is a common practice to

My attempt to configure Typescript to exclude specific files during compilation is not working as expected. Despite setting exclusions in my tsconfig.json file, the code from one of the excluded files (subClassA.ts) is still being included in the compiled ...

Employing ngModel in an option dropdown

I am having trouble passing an attribute from an API call to a submit function. I suspect it might have something to do with either the option select or how the input is being formatted. Encountering the error Error: No value accessor for form control wit ...

Incorporated iframe covering the entire browser window

Currently, I find myself in a strange predicament. The scenario involves a JSP+Servlet+Spring MVC application that is integrated within a parent application developed using Angular4 through an iframe. The issue arises when the Spring MVC app redirects to ...

Proper utilization of ngIf in conjunction with mat-cell

I am attempting to show a specific value only if the item possesses a certain property, but I keep seeing [object Object] instead. Here is my current method: <ng-container matColumnDef="name"> <th mat-header-cell *matHeaderCellDe ...

Using Angular 2's ngFor directive to iterate through arrays with access to first, last

In this example, I am attempting to make the first occurrence the default: plunkr However, I encountered the following error: Unhandled Promise rejection: Template parse errors: TypeError: Cannot read property 'toUpperCase' of undefined ...

When utilizing RxJS, the process of filtering Observable data may not function as expected if the filtering is carried out within a separate function rather than directly within the subscribe

While attempting to filter data from an external source using the RxJS filter on Observables, I encountered an issue where all records were returned instead of just the ones meeting the filtering criteria. This problem occurred when the code was within a l ...

An error occured in angular2: Cannot access the 'title' property of undefined

Here is the code snippet for my custom component: export class MoviedetailComponent implements OnInit { movie:any constructor( private getmovie: GetmovieService, private router: Router, private rout: ActivatedRoute ) { } ngOnInit() { this.r ...

The NestJS server encounters an unhandled exception leading to a server

As a newcomer to Nest.js and in the process of building a REST API server with typeorm, I have encountered an issue related to async functions. If I forget to include the await keyword while using an async function, it may result in an exception like &apos ...

Tips for resolving the AngularFire migration error related to observables

Recently, I decided to upgrade a project that had been untouched for over a year. Originally built on Angular 10, I made the jump to Angular 12. However, the next step was upgrading AngularFire from v6 to v7, and it appears there is an issue with typings. ...