0

I am trying to develop a data table that can be generic for the most common Objects in Salesforce (Accounts, Cases, Contacts, Leads, and Opportunities). Basically, I am trying to mimic the list view for those objects but have a Combobox at the top of the page that allows the user to select an object and the data table will refresh with that object's records.

I already have the child objectCombobox component and it's passing the selected object to the parent objectDatatable component. I also have an apex controller class that's running a SOQL query retrieving the records for each object.

Is there a way to have the wire functions in if-statements so when an object is selected from the objectCombobox component and passed to the objectDatatable component then the appropriate wire function/apex classes would be called and grab the correct records?

Also is there a way for columns to be dynamically generated rather than what's shown in most Salesforce Developer Documentation on Datatables where they hardcode the columns as a const? Like based on the records that are being pulled from the selected objects wire function assigns the names of those fields as column names?

ObjectController.cls

public with sharing class ObjectController {

    @AuraEnabled(cacheable=true)
    public static List <Account> getAccounts(){
        return [
            SELECT Name, BillingCity, Phone, Type
            FROM Account
        ];
    }

    @AuraEnabled(cacheable=true)
    public static List <Contact> getContacts(){
        return [
            SELECT Name, AccountId, Title, Phone, Email, OwnerId
            FROM Contact
        ];
    }

    @AuraEnabled(cacheable=true)
    public static List <Case> getCases(){
        return [
            SELECT CaseNumber, Subject, Status, CreatedDate, OwnerId
            FROM Case
        ];
    }

    @AuraEnabled(cacheable=true)
    public static List <Lead> getLeads(){
        return [
            SELECT Name, Company, Address, Email, Status
            FROM Lead
        ];
    }

    @AuraEnabled(cacheable=true)
    public static List <Opportunity> getOpportunities(){
        return [
            SELECT Name, AccountId, Amount, CloseDate, StageName, OwnerId
            FROM Opportunity
        ];
    }
}

objectCombobox.js

import {LightningElement, api} from 'lwc';

export default class ObjectCombobox extends LightningElement {

    @api selectedObjectValue;
    
    get options() {
        return [{
            
                label: "Account",
                value: 'account'
            },
            {
                label: "Contact",
                value: 'contact'
            },
            {
                label: "Case",
                value: 'case'
            },
            {
                label: "Lead",
                value: 'lead'
            },
            {
                label: "Opportunity",
                value: 'opportunity'
            },
        ];
    }

    handleChange(event) {
        this.selectedObjectValue = event.target.value;
        //console.log("Selcted value: " + this.selectedObjectValue);
        const selectedEvent = new CustomEvent("objectvaluechange", {
            detail: this.selectedObjectValue
        });
        this.dispatchEvent(selectedEvent);
    }
}

objectCombobox.html

<template>
    <lightning-combobox
        name="objects"
        value={selectedObjectValue}
        placeholder="Select an Object"
        options={options}
        onchange={handleChange}>
    </lightning-combobox>
</template>

objectDatatable.js

import { LightningElement, track, api, wire } from 'lwc';
import { updateRecord } from 'lightning/uiRecordApi';
import { deleteRecord } from 'lightning/uiRecordApi';
import { ShowToastEvent } from 'lightning/platformShowToastEvent';

import getAccounts from '@salesforce/apex/ObjectController.getAccounts';
import getCases from '@salesforce/apex/ObjectController.getCases';
import getContacts from '@salesforce/apex/ObjectController.getContacts';
import getLeads from '@salesforce/apex/ObjectController.getLeads';
import getOpportunities from '@salesforce/apex/ObjectController.getOpportunities';



export default class ObjectDatatable extends LightningElement {


    @track selectedObject;
    @track records;

    handleObjectChange(event) {
        this.selectedObject = event.detail;
        //console.log(this.selectedObject);
    }

}

objectDatatable.html

<template>
    <lightning-card title="Object Datatable" icon-name="custom:custom63">
        <div class="slds-m-around_medium">
            <c-object-combobox
                onobjectvaluechange={handleObjectChange}
            ></c-object-combobox>
        </div>
    </lightning-card>
</template>
1
  • Hi Diego, welcome to SFSE. Please take a moment to scroll through the tour and read How to Ask. This question is currently asking many things, making it broad and difficult to answer concisely. Please try to narrow the scope of this question, possibly splitting it up into multiple questions.
    – Adrian Larson
    Mar 1, 2021 at 16:31

1 Answer 1

2

I'd refactor your code so that you don't need to worry about it. Yes, you can indeed make the columns dynamic, you just need a mechanism for that. Here's a possible solution:

public with sharing class ObjectController {
    public class Column {
        @AuraEnabled public String fieldName;
        @AuraEnabled public String fieldLabel;
        @AuraEnabled public String fieldType;
        Column(String fName, String fLabel, String fType) {
            fieldName = fName;
            fieldLabel = fLabel;
            fieldType = fType;
        }
    }
    public class Response {
        @AuraEnabled public Column[] columns = new Column[0];
        @AuraEnabled public sObject[] records;
    }
    @AuraEnabled(cacheable=true) public static Response getObjects(String sourceType) {
        Response res = new Response();
        switch on sourceType {
            when 'Opportunity' {
                res.records = [SELECT Name, AccountId, Amount, CloseDate, toLabel(StageName), OwnerId FROM Opportunity];
                res.columns.add(new Column('Name','Name','text'));
                res.columns.add(new Column('AccountId','Account ID','text'));
                res.columns.add(new Column('Amount','Amount','currency'));
                res.columns.add(new Column('CloseDate','Close Date','date'));
                res.columns.add(new Column('StageName','Stage Name','text'));
                res.columns.add(new Column('OwnerId','Owner ID','text'));
            }
            when 'Account' {
                /* Do the same as above for account */
            }
            /* etc, etc */
        }
        return res;
    }
}

Now, your wire parts could be:

export default class ObjectDatatable extends LightningElement {
    @track selectedObject;

    handleObjectChange(event) {
        this.selectedObject = event.detail;
        //console.log(this.selectedObject);
    }
    @wire(getObjects, { sourceType: '$selectedObject' })
    objectData;
    get columns() {
        return objectData && objectData.data ? objectData.data.columns : [];
    }
    get records() {
        return objectData && objectData.data ? objectData.data.records : [];
    }
}

Obviously, you might need to work on flattening data or other problems, but the main point is it can definitely be dynamic in nature, for both columns displayed and the record data.

4
  • thank you I understand what your doing in the controller and then calling the appropriate wire statement in the js an populating records and columns based on the selected object passed. I am running into a bug when trying to implement the js. I am not sure if its a general bug or not but its "Unterminated string constant" on the sourceeType: ... section even though I am closing off the '$selectedObject' in quotes Mar 1, 2021 at 22:39
  • @DiegoDelgado Not sure what to say, but, I guess, double-check your quotes (don't mix " and ' as terminators), and don't use a template string (using ```/backtick characters). If you want, you can edit your question, post a new question, or we could create a chat room to discuss.
    – sfdcfox
    Mar 1, 2021 at 22:47
  • it was just vscode. I closed it and opened it back up and it went away. Could we create a chatroom? I just had a question on the apex and some errors that are being brought up when deploying to source? Mar 2, 2021 at 0:37
  • @DiegoDelgado You can join my chat.
    – sfdcfox
    Mar 2, 2021 at 0:54

You must log in to answer this question.

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