0

I've been following a tutorial by this website: http://santanuboral.blogspot.com/2017/02/display-records-with-rowspan-in.html as it has been the exact requirement I am looking for.

enter image description here

But I really want to practice incorporating latest technology from Salesforce, which is Lightning Web Components (LWC). So I've been trying to convert it to LWC. After multiple research, I have been able to create something. But upon deploying it on my devhub org and displaying it through a lightning tab, only the header part are displayed. There are no data on the body part.

Here's what I achieved so far:

contactLWC.html

<template>

    <table class="slds-table slds-table_cell-buffer slds-table_bordered ">
     <thead>
      <tr class="slds-line-height_reset">
       <th class="" scope="col">
        <div class="slds-truncate" title="contactModule">Module</div>
       </th>
       <th class="" scope="col">
        <div class="slds-truncate" title="contactName">Name</div>
       </th>
       <th class="" scope="col">
        <div class="slds-truncate" title="contactEmail">Email</div>
       </th>
       <th class="" scope="col">
        <div class="slds-truncate" title="contactPhone">Phone</div>
       </th>
      </tr>
     </thead>
     <tbody>
      <template if:true={mapData}>
       <template for:each={mapData} for:item="keyValue">
        <tr key={keyValue.key} class="slds-hint-parent">
            <th scope="col">
                <div>{keyValue.key}</div>
            </th>
            <template for:each={keyValue.value} for:item="value">
                <div key={value.Name}>
                    {value.Name}
                </div> 
                <div key={value.Email}>
                    {value.Email}
                </div> 
                <div key={value.Phone}>
                    {value.Phone}
                </div> 
            </template>
        </tr>      
       </template>
      </template>
     </tbody>
    </table>
</template>

contactLWC.js

import { LightningElement, track, wire } from 'lwc';

import getDataFromApex from '@salesforce/apex/ContactController.getData';

export default class contactLWC extends LightningElement {

    @track mapData = [];

    @wire(getDataFromApex) 
    wiredcontactdata({ data, error }) {
        if (data) {
            for(let key in data) {

                if (data.hasOwnProperty(key)) { 
                    this.mapData.push({key: key, value: data[key]});
                }
            }
        } else if (error) {
            window.console.log(error);
        }
    }

}

ContactController.cls

public class ContactController{

    public ContactController()
    {
    }

    @AuraEnabled(cacheable=true)

    public static List<String> getData()
    {

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

     List<Contact> contactList = [SELECT Name, Email, Phone, Module__c 
            FROM Contact 
            WHERE Module__c != null 
            ORDER BY Module__c];

     for(Contact contObj:contactList)
     {
      List<ContactWrapper> conWrapperList = new List<ContactWrapper>();

      if(mapModule.containsKey(contObj.Module__c))
      {

       conWrapperList = mapModule.get(contObj.Module__c);


       conWrapperList.add(new ContactWrapper(contObj));

       mapModule.put(contObj.Module__c, conWrapperList);


       moduleCountMap.put(contObj.Module__c, conWrapperList.size());
      }
      else
      {

       conWrapperList.add(new ContactWrapper(contObj));
       mapModule.put(contObj.Module__c, conWrapperList);


       moduleCountMap.put(contObj.Module__c, conWrapperList.size());
      }
     }


     moduleList = new List<String>(mapModule.keySet()); 

     return moduleList;

    }

    public Class ContactWrapper {

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

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


   }

Would really appreciate anyone's help. Hope someone could help me on this.

0

2 Answers 2

2

You need to import the apex method in lwc.

import getDataFromApex from '@salesforce/apex/ContactController.getData';

Change your method signature to return the map data. And change the return statement as well, like below.

Also, you need to add the auraEnabled to all the wrapper class members with getter/setters.

so the final code may look like.

public class ContactController {

    @AuraEnabled(cacheable=true)
    public static Map<String, List<ContactWrapper>> getData() {
        Map<String, List<ContactWrapper>> mapModule = new Map<String, List<ContactWrapper>>();
        Map<String, Integer> moduleCountMap = new Map<String, Integer>();
        //List<String> moduleList = new List<String>();

        List<Contact> contactList = [
            SELECT Name, Email, Phone, Module__c
            FROM Contact
            WHERE Module__c != null
            ORDER BY Module__c
        ];

        for (Contact contObj : contactList) {
            List<ContactWrapper> conWrapperList = new List<ContactWrapper>();

            if (mapModule.containsKey(contObj.Module__c)) {
                conWrapperList = mapModule.get(contObj.Module__c);

                conWrapperList.add(new ContactWrapper(contObj));

                mapModule.put(contObj.Module__c, conWrapperList);

                moduleCountMap.put(contObj.Module__c, conWrapperList.size());
            } else {
                conWrapperList.add(new ContactWrapper(contObj));
                mapModule.put(contObj.Module__c, conWrapperList);

                moduleCountMap.put(contObj.Module__c, conWrapperList.size());
            }
        }
        return mapModule;
    }

    public class ContactWrapper {
        public ContactWrapper(Contact contObj) {
            this.Name = contObj.Name;
            this.Email = contObj.Email;
            this.Phone = contObj.Phone;
            this.Module = contObj.Module__c;
        }
        @AuraEnabled
        public String Name { get; set; }
        @AuraEnabled
        public String Email { get; set; }
        @AuraEnabled
        public String Phone { get; set; }
        @AuraEnabled
        public String Module { get; set; }
    }
}
 

Also, you can take out the row span calculation out of the apex, and apex just have to return the data. You can calculate the row span in the JS controller itself. I have demonstrated that on my blog post SLDS table with Cell Merge in LWC

Instead of the wired property try wired method so you can log the errors on the console.

@wire(getDataFromApex) 
wiredContactdata({ error, data }) {
    if (data) {
        this.contactdata = data;
        this.error = undefined;
        console.log('data : ', JSON.stringify(data));
    } else if (error) {
        console.log('error : ', JSON.stringify(error));
        this.error = error;
        this.contactdata = undefined;
    }
}

Also you will need to replace contactdata.data with contactdata in your html.

14
  • 1
    Thanks for your immediate response, and also for your blog recommendation! Will check both of it then let you know the result.
    – Ertyq
    Commented Jun 8, 2020 at 11:28
  • 1
    check the apex debug logs, also instead of wired property try wire method so you can check the console logs. here is the example. I will update that in my answer Commented Jun 8, 2020 at 12:00
  • 1
    yes, that is also possible you just need to replace the hardcoded data with data queried from the apex. Commented Jun 8, 2020 at 12:01
  • 1
    you need to convert the map into array. check this @Ertyq Commented Jun 8, 2020 at 13:09
  • 1
    can you please post a new question with that code? Commented Jun 8, 2020 at 14:42
3

You need to add @AuraEnabled to your Wrapper properties

     @AuraEnabled
     public String Name {get;set;}
     @AuraEnabled
     public String Email {get;set;}
     @AuraEnabled
     public String Phone {get;set;}
     @AuraEnabled
     public String Module {get;set;}
1
  • points out one problem +1. Commented Jun 8, 2020 at 11:34

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .