• Yara Elmhamid
  • NEWBIE
  • 0 Points
  • Member since 2022

  • Chatter
    Feed
  • 0
    Best Answers
  • 0
    Likes Received
  • 0
    Likes Given
  • 2
    Questions
  • 1
    Replies
Hello

I would like to create a lightning datatable (or another other type of lightning tables) in my aura component in order to display a nested data.
The data is composed of accounts with their related contacts. I built it using a wrapper class in the apex controller and then i pass it to the component through a helper in order to display it in my component.

I tested the accessibility of that data in my component ( i managed to display it as simple text) but after trying to organize it in a datatable, this later is not displaying any of my data.

My question is how can i define the attribute column of the datatable so it allows me to show the accounts with their related contacts? 

Here is what i made.

Apex controller
public with sharing class ReferralProgramApexController {
      @AuraEnabled
    public static List<AccountRelatedContactsWrapper> getNestedAccounts() {
  
        //create a list to store in it the custom objects of type AccountRelatedContactsWrapper
        List<AccountRelatedContactsWrapper> AccountsContactsWrapperList = new List<AccountRelatedContactsWrapper>();
        //retreive 3 accounts each with all its related contacts
        List<Account> AccountsContactsNestedList = [SELECT Id, Name,
                                    (SELECT Id, Email, phone From Contacts)
                                    FROM Account Limit 3];
        //check if the accounts list is not empty
        if(!AccountsContactsNestedList.isEmpty()){
            //loop over the retrieved accounts
            for(Account acc : AccountsContactsNestedList){
                //create a wrapper object of type AccountRelatedContactsWrapperand add it to the objects list 
                AccountsContactsWrapperList.add(new AccountRelatedContactsWrapper(acc, acc.Contacts));
            }
        }
        return AccountsContactsWrapperList; 
    }

    // wrapper class with @AuraEnabled and {get;set;} properties 
    public class AccountRelatedContactsWrapper{
        //properties
        @AuraEnabled
        public Account accRecord{get;set;}
        @AuraEnabled
        public List<Contact> contactList{get;set;}
        //constructor
        public AccountRelatedContactsWrapper(Account accRecord,List<Contact> contactList){
            this.accRecord = accRecord;
            this.contactList = contactList;
        }
       
    }
    
}
Data structure i get 
User-added image
helper
({
	getData : function(component) {
        // Create a remote method call (Action) from apex controller
        let action = component.get("c.getNestedAccounts");
        // Add callback behavior for when response is received
        action.setCallback(this, function(response) {
            let state = response.getState();
            if (state === "SUCCESS") {
                //set the component accountlList attribute with fetched data
                component.set("v.AccountNestedList", response.getReturnValue());                   
            }
            else {
                console.log("Failed with state: " + state);
            }
        });
        // Send action off to be executed
        $A.enqueueAction(action);
    }
})
controller 
({
    // Load Accounts from Salesforce
    FetchData: function(component, event, helper) {
        //set the datatable according to the data to be fetched
        component.set('v.columns', [
            {label: 'Account Id', fieldName: 'accRecord.Id', type: 'text' },
            {label: 'Name', fieldName: 'accRecord.Name', type: 'text' },
            {label: 'Email', fieldName: 'contactList.Email', type: 'text' },
            {label: 'Phone', fieldName: 'contactList.Phone', type: 'text' }
        ]);
        helper.getData(component);
    }
  
})

component definition
<aura:component controller = "ReferralProgramApexController"
                implements="force:appHostable,flexipage:availableForAllPageTypes,flexipage:availableForRecordHome,force:hasRecordId,forceCommunity:availableForAllPageTypes,force:lightningQuickAction" access="global" >

    <aura:attribute name="AccountNestedList" type="object[]"/>
    <aura:attribute name="columns" type="List"/>

    <aura:handler name="init" action="{!c.FetchData}" value="{!this}"/>

    <aura:if isTrue="{!not(empty(v.AccountNestedList))}">
         <lightning:datatable data="{!v.AccountNestedList.accRecord}" 
                         columns="{!v.columns}" 
                         keyField="Id"
                         hideCheckboxColumn="true"/>
      
      <!--  <aura:iteration items="{!v.AccountNestedList}" var="obj" indexVar="sNo"> 
                 {!obj.accRecord.Name}
            <aura:iteration items="{!obj.contactList}" var="cont"> 
                {!cont.Email} {!cont.Phone}
            </aura:iteration> 
        </aura:iteration>         
        -->
     <aura:set attribute="else">
                <div Style="text-align : center"> " There are no contacts " </div>
            </aura:set>
     </aura:if>
    
    
    
</aura:component>

​​​​​​
Thank you in advance.
Hello.

Its my first time working on Apex triggers and i have read that we must not run our SoQL queries inside of a bulk loop (same for DML calls). But i am struggling with that as i have a pretty complicated query inside my loop to make it work out of the loop. a kind of 2 level query that uses 4 sObjects that reference each others (Task, Contact, Account, Opportunity)

This is the Apex trigger i want to make it follow the best practices (i tested this version and it fires my trigger all good).

---------------------
//this trigger is used to update the opportunities retrieved from an account(s) related to the contact of this task that fires the trigger when it is marked as completed.

trigger Close_won_opportunities on Task (after update) {
    CloseWonOpportunitiesHandler taskHandler = new CloseWonOpportunitiesHandler();
    taskHandler.UpdateOpportunities(trigger.new);
    }

---------------------

public class CloseWonOpportunitiesHandler {
    public void UpdateOpportunities(List<Task> tasList){
        //create opportunities list
        List<Opportunity> OppsToUpdate = new List<Opportunity>();         
        //looping over the tasks list
        for(Task t : tasList){
            //if the task was created by a lead conversion and now is completed 
            if(t.leadConversion__c && t.Status=='Completed'){
                //get all the opportunities of the accounts related to the contact of this task
                 List<Opportunity> relatedOpps = [SELECT Id, StageName FROM Opportunity WHERE AccountId IN (Select accountID from Contact where Id=:t.WhoId)];
                //Mark these opportunities as closed won
                for(Opportunity opp : relatedOpps){
                    opp.StageName = 'Closed Won';
                    OppsToUpdate.add(opp);
                }
            } 
      }
    //DML update opportunities
                upsert OppsToUpdate;
    }
}
---------------------

i tried solving it using nested Maps and multi level Queries but unfortunately i couldnt find the right way to do it.

i hope someone can help me with this.
thank you in advance.
Hello.

Its my first time working on Apex triggers and i have read that we must not run our SoQL queries inside of a bulk loop (same for DML calls). But i am struggling with that as i have a pretty complicated query inside my loop to make it work out of the loop. a kind of 2 level query that uses 4 sObjects that reference each others (Task, Contact, Account, Opportunity)

This is the Apex trigger i want to make it follow the best practices (i tested this version and it fires my trigger all good).

---------------------
//this trigger is used to update the opportunities retrieved from an account(s) related to the contact of this task that fires the trigger when it is marked as completed.

trigger Close_won_opportunities on Task (after update) {
    CloseWonOpportunitiesHandler taskHandler = new CloseWonOpportunitiesHandler();
    taskHandler.UpdateOpportunities(trigger.new);
    }

---------------------

public class CloseWonOpportunitiesHandler {
    public void UpdateOpportunities(List<Task> tasList){
        //create opportunities list
        List<Opportunity> OppsToUpdate = new List<Opportunity>();         
        //looping over the tasks list
        for(Task t : tasList){
            //if the task was created by a lead conversion and now is completed 
            if(t.leadConversion__c && t.Status=='Completed'){
                //get all the opportunities of the accounts related to the contact of this task
                 List<Opportunity> relatedOpps = [SELECT Id, StageName FROM Opportunity WHERE AccountId IN (Select accountID from Contact where Id=:t.WhoId)];
                //Mark these opportunities as closed won
                for(Opportunity opp : relatedOpps){
                    opp.StageName = 'Closed Won';
                    OppsToUpdate.add(opp);
                }
            } 
      }
    //DML update opportunities
                upsert OppsToUpdate;
    }
}
---------------------

i tried solving it using nested Maps and multi level Queries but unfortunately i couldnt find the right way to do it.

i hope someone can help me with this.
thank you in advance.