[SalesForce] Group data and display on VF Page (use of rowspan)

I have 5 columns , out of which if data of 4 columns are repeating , the 5th column needs to be grouped.

Name Designation Email Phone Module

So if we have multiple modules assigned to a single person , one single row needs to be displayed.

Trial so far :

Storing data from 3rd party into map in 4 column key + value format

mapAccountTeam.put(Con.Name+Con.Designation+Con.Email+Con.Phone, contactList);

Wrapper Class

public Class GroupWrapper {
    public List<Type> contactWrapperList {get; set;}
    public String groupedVal {get; set;}
    public Integer count {get {return contactWrapperList.size(); } set;}
    }

Not sure how to model the two apex repeat based on the key/value.

Can somebody help?

Controller:

for(CustomerContact__c CustCon : contactList){
        if(mapModule.containsKey(CustCon.Name+CustCon.Designation+CustCon.Email+CustCon.Phone)) {
                List<ContactWrapper> conWrapperList = mapModule.get(CustCon.Name+CustCon.Designation+CustCon.Email+CustCon.Phone);
                ContactWrapper conWrapObj = new ContactWrapper();
                conWrapObj.name = CustCon.Name;
                conWrapObj.name = CustCon.Designation;
                conWrapObj.name = CustCon.Module;
                conWrapObj.name = CustCon.Email;
                conWrapObj.name = CustCon.Phone;
                conWrapperList.add(conWrapObj);
                mapModule.put(CustCon.Name+CustCon.Designation+CustCon.Email+CustCon.Phone, conWrapperList);
        }

        else
         {
        List<ContactWrapper> conWrapperList = new List<ContactWrapper>();
        ContactWrapper conWrapObj = new ContactWrapper();
        conWrapObj.name = CustCon.Name;
                conWrapObj.name = CustCon.Designation;
                conWrapObj.name = CustCon.Module;
                conWrapObj.name = CustCon.Email;
                conWrapObj.name = CustCon.Phone;
                conWrapperList.add(conWrapObj);
                mapModule.put(CustCon.Name+CustCon.Designation+CustCon.Email+CustCon.Phone, conWrapperList);      
    }

      }
       moduleList = new List<String>(mapModule.keySet()); 
       system.debug('moduleList'+moduleList);    

VF:

<apex:repeat id="myRepeatHeader" value="{!moduleList}" var="key">
    <tr>    

        <td rowspan="{!mapModule[key].size()}">
        <apex:outputText value="{!mapModule[key].Name}"/>
        <apex:outputText value="{!mapModule[key].Designation}"/>
        <apex:outputText value="{!mapModule[key].Email}"/>
        <apex:outputText value="{!mapModule[key].Phone}"/>   
        </td>
        <apex:repeat id="contactDetails" value="{!mapModule[key]}" var="con">
        <tr>
            <td><apex:outputText value="{!con.Module}"/></td>

        </tr>
       </apex:repeat>
    </tr>
</apex:repeat> 

Table :

Name Designation Email Phone Module

Roger Manager abcd@abcd.com 555 Module 5 Module 6

Rita Senior Manager xyz@abcd.com 222 Module 1 Module 2

Best Answer

I will take this approach to prepare the structure like this:

1) Create a ContactWrapper with all the Contact attributes.

2) In getData() method, retrieve the Contact List firing SOQL query and prepare the desired map i.e. mapModule which contains ModuleName as Key and List<ContactWrapper>. In that method, prepare a List of ModuleNames from mapModule.keySet().

public class ContactController{
    //map to capture Module Name and List of Contacts
    public Map<String, List<ContactWrapper>> mapModule {get;set;} 

    //map to capture Module Name and count of Contact which will be used to define rowspan.
    public Map<String, Integer> moduleCountMap{get;set;}

    //to capture list of Module Names
    public List<String> moduleList {get;set;}

    public ContactController()
    {
        mapModule = new Map<String, List<ContactWrapper>>();
        moduleCountMap = new Map<String, Integer>();
        moduleList = new List<String>();
    }

    //prepare data to display in Visualforce.
    public void getData()
    {
        List<Contact> contactList = [SELECT Name, Phone, Email, Module__c 
                                            FROM Contact 
                                            WHERE Module__c !=null 
                                            ORDER BY Module__C LIMIT 10];

        //grouped into module and prepare the map
        for(Contact conObj:contactList)
        {
            List<ContactWrapper> conWrapperList = new List<ContactWrapper>();
            //verify map already contains same Module Name
            if(mapModule.containsKey(conObj.Module__c))
            {
                //retrieve the list of existing contact
                conWrapperList = mapModule.get(conObj.Module__c);

                //put the new contact to the list
                conWrapperList.add(new ContactWrapper(conObj));

                mapModule.put(conObj.Module__c, conWrapperList);
                modulecountMap.put(conObj.Module__c, conWrapperList.size());
            }
            else
            {
                //create a new map of Module Name
                conWrapperList.add(new ContactWrapper(conObj));
                mapModule.put(conObj.Module__c, conWrapperList);
                modulecountMap.put(conObj.Module__c, conWrapperList.size());
            }
        }

        //create a list of Module Names which will be helpful to iterate
        moduleList = new List<String>(mapModule.keySet());  
    }

    public Class ContactWrapper {

        public ContactWrapper(Contact conObj)
        {
            this.Name = conObj.Name;
            this.Phone = conObj.Phone;
            this.Email = conObj.Email;
            this.Module = conObj.Module__c;
        }

        public String Name {get;set;}
        public String Designation {get;set;}
        public String Phone {get;set;}
        public String Email {get;set;}
        public String Module {get;set;}
    }
}

Visualforce

1) First, repeat through moduleList which contains all the Module Name as key.

2) To determine, td rowspan get the size by {!modulecountMap[key]}.

3) Create an inner repeat which have List of ContactWrapper which we can easily retrieve by {!mapModule[key]}

<apex:page controller="ContactController" action="{!getData}">
  <table border="1">
   <tr>
    <th>Group</th>
    <th>Name</th>
    <th>Phone</th>
    <th>Email</th>
    </tr>    
     <apex:repeat id="myRepeatHeader" value="{!moduleList}" var="key">         
         <apex:variable var="count" value="{!1}"/>            
            <apex:repeat id="contactDetails" value="{!mapModule[key]}" var="att">
                <tr>
                    <apex:outputPanel layout="none" rendered="{!count==1}">
                        <td rowspan="{!(modulecountMap[key])}"><apex:outputText value="{!att.Module}"/></td>
                    </apex:outputPanel>
                    <td><apex:outputText value="{!att.Name}"/></td>
                    <td><apex:outputText value="{!att.Phone}"/></td>
                    <td><apex:outputText value="{!att.Email}"/></td>

                    <apex:variable var="count" value="{!count+1}"/>
                 </tr>
            </apex:repeat>
    </apex:repeat>    
    </table>
</apex:page>

I have tried to visualize like this:

Table data

At my dev org, it is showing like this. I am not showing designation column

rowspan

To get a help on how to use rowspan, refer td row span

Related Topic