Lightning Tree Grid to search Account and display related Contacts and Opportunities in Salesforce

Sample Code:

Apex Class:

public with sharing class AccountController {  
 
    @AuraEnabled( cacheable = true )  
    public static List< Account > fetchAccounts( String searchKey ) {  
      
        String strKey = '%' + searchKey + '%';  
        System.debug( 'strKey is ' + strKey );
        return [
            SELECT Id, Name, Industry,
            ( SELECT Id, FirstName, LastName FROM Contacts ),
            ( SELECT Id, Name, Stagename FROM Opportunities )
            FROM Account
            WHERE Name LIKE: strKey LIMIT 10
        ];  
          
    }  
      
}
   
Lightning Web Component:
HTML:

<template>            
    <lightning-card title="Search Accounts" icon-name="custom:custom63">      
        <div class="slds-m-around_medium">        
            <lightning-input type="search" onchange={handleKeyChange} class="slds-m-bottom_small" label="Search">  
            </lightning-input><br/>
            <lightning-button variant="brand" label="Search" onclick={handleSearch}></lightning-button>
            <template if:true={gridData}>           
                <lightning-tree-grid
                    columns={gridColumns}
                    data={gridData}
                    key-field="Id"
                    hide-checkbox-column=true>
                </lightning-tree-grid>                   
            </template>            
            <template if:true={error}>        
                {error}>                        
            </template>        
        </div>        
    </lightning-card>        
</template>  

JavaScript:
import { LightningElement } from 'lwc';  
import fetchAccounts from '@salesforce/apex/AccountController.fetchAccounts';  
    
export default class accountSearchLWC extends LightningElement {  
    
    gridColumns = [ {
        type: 'text',
        fieldName: 'Name',
        label: 'Name'
    },
    {
        type: 'text',
        fieldName: 'Industry',
        label: 'Industry'
    },
    {
        type: 'text',
        fieldName: 'FirstName',
        label: 'FirstName'
    },
    {
        type: 'text',
        fieldName: 'LastName',
        label: 'LastName'
    },
    {
        type: 'text',
        fieldName: 'OpptyName',
        label: 'Opportunity Name'
    },
    {
        type: 'text',
        fieldName: 'StageName',
        label: 'Opportunity Status'
    } ];
    gridData;
    error;  
    searchKey;
    
    handleKeyChange( event ) {  

        this.searchKey = event.target.value;
    }

    handleSearch() {

        console.log( 'Search Key is ' + this.searchKey );
    
        if ( this.searchKey ) {  
    
            fetchAccounts( { searchKey: this.searchKey } )    
            .then( result => {  
                
                console.log( 'Retrieved data is ' + JSON.stringify( result ) );
                let tempData = JSON.parse( JSON.stringify( result ) );

                for ( let i = 0; i < tempData.length; i++ ) {
                    
                    let cons = tempData[ i ][ "Contacts" ];
                    delete tempData[ i ][ "Contacts" ];
                    let childRecords = cons ? cons : [];
                    let opps = tempData[ i ][ "Opportunities" ];

                    for ( let opp in opps ) {

                        opps[ opp ].OpptyName = opps [ opp ].Name;
                        delete opps [ opp ].Name;
                        childRecords.push( opps[ opp ] );

                    }

                    delete tempData[ i ][ "Opportunities" ];                
                    console.log( 'Child Records ' + JSON.stringify( childRecords ) );
                    tempData[ i ]._children = childRecords;

                }

                console.log( 'Final Data ' + JSON.stringify( tempData ) );
                this.gridData = tempData;
    
            } )  
            .catch( error => {  
    
                this.error = error;  
    
            } );  
    
        } else  {
        
            this.gridData = undefined;  
        
        }
    
    }  
    
}  

JS-meta.xml:
<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>52.0</apiVersion>
    <isExposed>true</isExposed>
    <targets>
        <target>lightning__Tab</target>
    </targets>
</LightningComponentBundle>


Output: