function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
ryanschierholzryanschierholz 

Show grouped data together in Lightning web component.

I am building a list of our preferred vendors and want to show it in a custom lightning web component. I would like all vendors of the same 'Category' to be listed together, with just one header. 
User-added image

As you can see, when there are multiple vendors in one cateogry, the category name/head displays twice. I am sure I could get what I need, through making multiple calls in apex (one for each category), but it seems ideal and more efficient to get all the vendors in one call, and then just adjust their grouping in the lightning web component. 

I query the data in the controller, then display it in the lwc as such: 
<template for:each={vendors.data} for:item="vendor">
                <div key={vendor.Id}>                   
                    <div class="slds-text-heading_small">{vendor.Category_Name__c}</div>
                    <p><lightning-formatted-rich-text value={vendor.Vendor__c} ></lightning-formatted-rich-text></p>
                </div>
            </template>

 
Best Answer chosen by ryanschierholz
ryanschierholzryanschierholz
For the solution, check this out: https://developer.salesforce.com/forums/?id=9062I000000Xn7oQAC 

All Answers

Alain CabonAlain Cabon
Hi Ryan,

<template if:true> can be used for a conditional display.
 
<template>
    <lightning-card title="HelloForEach" icon-name="custom:custom14">
        <ul class="slds-m-around_medium">
            <template for:each={contacts} for:item="contact">
                <li key={contact.Id}>
                    <template if:true={contact.First} ><b>{contact.Category}</b><br/></template>
                    {contact.Name}, {contact.Title}
                </li>
            </template>
        </ul>
    </lightning-card>
</template>
 
import { LightningElement, track } from 'lwc';

export default class loops extends LightningElement {
    contacts = [
        {
            Id: 1,
            Name: 'Amy Taylor',
            Title: 'VP of Engineering',
            Category:'One',
            First:true
        },
        {
            Id: 2,
            Name: 'Michael Jones',
            Title: 'VP of Sales',
            Category:'One',
            First:false
        },
        {
            Id: 3,
            Name: 'Jennifer Wu',
            Title: 'CEO',
            Category:'Two',
            First:true

        },
        {
            Id: 4,
            Name: 'John Smith',
            Title: 'Developer',
            Category:'Two',
            First:false
        },
    ];
}

Another solution is a map with nested loops.
ryanschierholzryanschierholz
The issue is, the data is coming from a custom object, Review__c, in which the category is a Picklist. So, I can't see how I could dynamically mark items as 'first:true/false' unless there is some other programming/automation on that object, which seems to be excessive. 

I am wondering if I query the categories (and count) of Review__c records, then have a loop for that, then show the matching/applicable records for each category. Still feels like that would be excessive. I'm always looking/hoping for a more simple solution. :) 

I think I may need to explore your other solution: 'a map with nested loops' and/or how to put the data into an array in the lwc to manipulate it there, as opposed to passing it directly to the .html file. 
Alain CabonAlain Cabon

With nested loops..

A key is necessary for each loop.
 
<template>
    <lightning-card title="HelloForEach" icon-name="custom:custom14">
        <ul class="slds-m-around_medium">
            <template for:each={Contacts} for:item="contact">
                <div key={contact.Category}><b>{contact.Category}</b><br /></div>
                <template for:each={contact.Persons} for:item="person">
                    <li key={person.Id}>
                        {person.Name}, {person.Title}
                    </li>
                </template>
            </template>
        </ul>
    </lightning-card>
</template>

import {
    LightningElement
} from 'lwc';

export default class Loops2 extends LightningElement {

    Contacts = [{
            Category: 'One',
            Persons: [{
                    Id: 1,
                    Name: 'Amy Taylor',
                    Title: 'VP of Engineering'
                },
                {
                    Id: 2,
                    Name: 'Michael Jones',
                    Title: 'VP of Sales'
                }
            ],
        },
        {
            Category: 'Two',
            Persons: [{
                    Id: 3,
                    Name: 'Jennifer Wu',
                    Title: 'CEO',
                },
                {
                    Id: 4,
                    Name: 'John Smith',
                    Title: 'Developer'
                }
            ],
        },
    ];
}


 
ryanschierholzryanschierholz
Hey, I found a solution! However, because I found a solution, I made things more complicated. :) 

So, what I did was use a new custom object Category instead of the picklist. With that, I am able to use nested SOQL to get an array of items and then loop over them to show the results how I had hoped from this. However, this was a little slice of what I want/need. Ultimately, I want Super Cateogries as well, but SOQL doesn't support nesting more than once. So, I was able to use nested code like this:
SELECT Id, Name,(SELECT Id, Vendor__c, Category__r.Standard_Name__c, Phone__c FROM Reviews__r ) FROM Super_Category__c

To get my list that I can then iterate over in the lightning web component:
<template for:each={vendorsFromSc.data} for:item="sc">
                <div key={sc.Id} >
                    <div class="slds-text-heading_small">{sc.Name}</div>
                        <template for:each={sc.Reviews__r} for:item="vendor">
                            <div key={vendor.Id} class={vendor.MyVendor__c}>

                                <div class="slds-text-title">{vendor.Category__r.Standard_Name__c}</div>
 
                            </div>
                        </template>
                    </div>
                
            </template>

Producing a nested display as such:
User-added image

However, now the goal is to have each Category (i.e. Mortgage & Lending Services) just show once under it's Super Category (Real Estate Services). 

I keep reading about Wrapper Classes, but that's not in my wheel house yet, so I haven't had any success with that. 

The other option would be to get the data from Review__c object and then in the LWC in Javascript, somehow iterate over it to put it into a nested array like so: 
 
superCategories = [
        {
            Name: 'Additions',
            Categories: [
                {
                    Name: 'Bathroom Additions',
                    Reviews: [
                        {
                            Vendor: 'Jay at Pritches Closets',
                            Rating: 5,
                            Comment: 'this is the comment',
                            Phone: '8005551234'
                        }
                    ]
                },
                {
                    Name: 'Kitchen Additions',
                    Reviews: [
                        {
                            Vendor: 'Phil Dunphy',
                            Rating: 4,
                            Comment: 'this is the comment',
                            Phone: '8005551234'
                        }
                    ]
                }
            ]
        }
        
    ];

 
ryanschierholzryanschierholz
For the solution, check this out: https://developer.salesforce.com/forums/?id=9062I000000Xn7oQAC 
This was selected as the best answer
Victoria UkatuVictoria Ukatu
Hi Ryan, your solution that made things more complicated from November 8, 2019 gives me an idea about how I can use something similar in my code. Except I'm having a hard time following where some parts come from: would you be willing to share the other files too, like the Apex class? Also, can you explain what Reviews__c is, and how that relates to everything else, like MyVendor__c? The relationship between Super Category and Category is pretty clear though. Thank you! :)
ryanschierholzryanschierholz
The Apex class is pretty well shown on the other page that has the solution: https://developer.salesforce.com/forums/?id=9062I000000Xn7oQAC 

Review__c is a custom object of the ratings for the vendors (i.e. 5 star rating for Jay, etc). MyVendor__c is so the list can be filtered if the review was added by the user.