Salesforce Lightning Web Component: Dynamic Column Selection in Lightning Datatable


Today in this post we will see how to create Lightning Data Table where we can dynamically select the columns of lightning data table.
Below are the properties of this Lightning Data Table:
  1. User can select any column for Lightning Data Table
  2. User can select only those fields on which user has FLS.
  3. User can re-arrange the order of Columns in Data Table.
So in UI we will show one Dual List box where user can select any field for table. Once user will select the fields and click on save then selected fields will be visible on UI:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
<template>
    <lightning-card  title="Dynamic Lead Table">
        <lightning-button label="Modify Columns" slot="actions" onclick={showColumnSelectionWindow}></lightning-button>
        <p class="slds-p-horizontal_small">
            <lightning-datatable key-field="Id" data={objectData} columns={fieldsForCloumns}>
            </lightning-datatable>
        </p>
    </lightning-card>

    <template if:true={iscolumnWindow}>
        <section role="dialog" tabindex="-1" aria-labelledby="modal-heading-01" aria-modal="true" aria-describedby="modal-content-id-1" class="slds-modal slds-fade-in-open">
            <div class="slds-modal__container">
              <header class="slds-modal__header">
                <div class="slds-text-heading_large">Select Column for Data Table</div>
              </header>
              <div class="slds-modal__content slds-p-around_medium">
                <lightning-dual-listbox name="fieldSelection"
                            label="Select Fields (at least 5 and at most 10)"
                            source-label="Available Fields"
                            selected-label="Selected Field"
                            field-level-help="Select fields which you want to see in data table."
                            options={allFields}
                            min={minField}
                            max={maxField}
                            value={allSelectedField}
                            onchange={updateSelectedColumns}></lightning-dual-listbox>
              </div>
              <footer class="slds-modal__footer">
                <lightning-button name="cancelAction" class="slds-p-around_x-small" label="Cancel" onclick={closeModel}></lightning-button>
                <lightning-button name="saveAction"  class="slds-p-around_x-small" label="Save" onclick={closeModel} variant="brand"></lightning-button>
              </footer>
            </div>
          </section>
          <div class="slds-backdrop slds-backdrop_open"></div>
    </template>
</template>

Now lets take a look into Java Script logic:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
import { LightningElement, track, wire, api } from 'lwc';
import getField from '@salesforce/apex/DynamicColumnTableHandler.getAllColumnsDetail';
import getAllData from '@salesforce/apex/DynamicColumnTableHandler.showAddData';

export default class DynamicColumnofTable extends LightningElement {
    @track iscolumnWindow = false;
    @track minField;
    @track maxField;
    @track allFields = [];
    @track allSelectedField = [];
    @api objectData = [];
    @track columnArrays = [];
    @track fieldsForCloumn = [];
 
    @api 
    get fieldsForCloumns(){
        return this.fieldsForCloumn;
    }
    set fieldsForCloumns(val){
    }

    @wire(getField, {objectApiName : 'Lead'}) setObjectField({error, data}){
        if(data){
            const fields = [];
            for(let key in data){
                fields.push({
                    label : data[key],
                    value :key
                })
            }
            this.allFields = fields;
        }else if(error){
            console.log(error);
        }
    };

    updateSelectedColumns(event){
        const valueSelected = event.target.value;
        this.allSelectedField = valueSelected;
    }

    showColumnSelectionWindow(event){
        this.iscolumnWindow = true;
    }

    closeModel(event){
        const eventName = event.target.name;
        if(eventName === 'saveAction'){
            const selectedFields = this.allSelectedField;
            const addfields = [];
            const fieldAPI = [];
            for(let i = 0; i < selectedFields.length; i++){
                for(let key in this.allFields){
                    if(this.allFields[key].value === selectedFields[i]){
                        addfields.push({
                            label : this.allFields[key].label,
                            fieldName : this.allFields[key].value
                        });
                        fieldAPI.push(this.allFields[key].value);
                    }
                }
            }
            this.fieldsForCloumn = addfields;
            this.columnArrays = fieldAPI;
            getAllData({selectedField : JSON.stringify(this.columnArrays), objectName: 'Lead'}).then(result =>{
                let allrecords = [];
                for(let i = 0; i < result.length; i++){
                    let rowData = result[i];
                    let row = rowData;
                    row.Id = rowData.Id;
                    for(let col in this.fieldsForCloumns){
                        if(col.fieldName != 'Id'){
                            row[col.fieldName] = rowData[col.fieldName];
                        }
                    }
                    allrecords.push(row);
                }
                this.objectData = allrecords;
            }).catch(error => {
                window.alert(error);
            })
        }
        this.iscolumnWindow = false;
    }
}

Apex Class:

In below apex class there are two method. First one is getting all the fields of Sobject which is passed from LWC to Apex Class. Second method is processing the records based on Columns selection.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
public with sharing class DynamicColumnTableHandler {
    @AuraEnabled(cacheable = true)
    public static Map<String, String> getAllColumnsDetail(String objectApiName){
        Map<String, String> fieldToLabelMap = new Map<String, String>();
        Schema.SObjectType loadSchema = Schema.getGlobalDescribe().get(objectApiName);
        Map<String, Schema.SObjectField> fieldMap = loadSchema.getDescribe().fields.getMap();
        for (Schema.SObjectField fld: fieldMap.values()) {
            if(fld.getDescribe().isAccessible()){
                fieldToLabelMap.put(fld.getDescribe().getName(), String.valueOf(fld.getDescribe().getLabel()));
            }
        }
        return fieldToLabelMap;
    }

    @AuraEnabled
    public static List<Sobject> showAddData(String selectedField, String objectName){
        List<String> fieldList = (List<String>) JSON.deserialize(selectedField, List<String>.class);
        String query = 'Select Id';
        for(String str : fieldList){
            query+= ', ' + str ;
        }
        query+= ' from ' + objectName;
        System.debug('Test: '+ query);
        List<Sobject> sobjectData = Database.query(query);
        return sobjectData;
    }
}

Example:



Comments

Followers

Popular posts from this blog

Salesforce LWC: Multi-Record Creation using Lightning Web Component

Salesforce LWC: Basic Drag and Drop Functionality