Pop up from Salesforce lightning-datatable

Pop up from Salesforce lightning-datatable

LightningModal can be used in the Salesforce Lightning Web Component lightning-datatable for Pop Up window or screen.

Please check the following to know more about the lightning-modal in the Salesforce Lightning Web Component.

Sample Apex Class to fetch Accounts and related Contacts:

public with sharing class AccountSearchController {

    @AuraEnabled( cacheable = true )
    public static List < Account > fetchAccounts( 
        String strAccountName, 
        List < String > listSelectedIndustries
    ) {

        strAccountName = '%' + strAccountName + '%';
        System.debug(
            'Account Name is ' + 
            strAccountName
        );
        System.debug(
            'Account Industries are ' + 
            listSelectedIndustries
        );

        List < Account > listAccounts = [
            SELECT Id, Name, Industry, Type,
            (
                SELECT Id, AccountId, Title, Name
                FROM Contacts
            )
            FROM Account
            WHERE Name LIKE: strAccountName
            AND Industry IN: listSelectedIndustries
        ];

        return listAccounts;

    }

}

Sample Lightning Web Component for Pop up:

HTML:

<template>
    <lightning-modal-header 
        label="Contacts">        
    </lightning-modal-header>
    <lightning-modal-body>
        <lightning-datatable 
            key-field="Id"
            data={listContacts}
            columns={columns}
            hide-checkbox-column 
            show-row-number-column>
        </lightning-datatable>
    </lightning-modal-body>
    <lightning-modal-footer>
        <lightning-button 
            label="Close"
            onclick={handleClose}>
        </lightning-button>
    </lightning-modal-footer>
</template>

JavaScript:

import { api } from 'lwc';
import LightningModal from 'lightning/modal';

export default class ContactsPopUp extends LightningModal  {
    
    @api listContacts;
    columns = [ 
        { label: 'Name', fieldName: 'Name' }, 
        { label: 'Title', fieldName: 'Title' }
    ];

    handleClose() {

        this.close(
            'Closed'
        );
        
    }

}  

js-meta.xml:

<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>62.0</apiVersion>
    <isExposed>true</isExposed>
</LightningComponentBundle>

Sample Lightning Web Component for testing the Pop up:

HTML:

<template>
    <div class="slds-box slds-theme--default">
        <lightning-layout vertical-align="center">
            <lightning-layout-item padding="around-small">
                <lightning-input 
                type="text" label="Account Name" 
                value={accountName} onchange={handleChange} 
                class="slds-p-around_medium">
                </lightning-input>
            </lightning-layout-item>
            <lightning-layout-item padding="around-small">
                Industry<br/>
                <template lwc:if={optionsForIndustry}>
                    <lightning-button-menu 
                        label={industryLabel}
                        onselect={handleIndustryChange}>
                        <template iterator:it={optionsForIndustry}>
                            <lightning-menu-item 
                                value={it.value.label} 
                                label={it.value.value}
                                checked={it.value.isSelected}
                                key={it.value.value}>
                        </lightning-menu-item>
                        </template>
                    </lightning-button-menu>
                </template>
            </lightning-layout-item>
            <lightning-layout-item padding="around-small">
                <br/>
                <lightning-button 
                    variant="brand" 
                    icon-name="utility:record_lookup" 
                    label="Search Accounts" 
                    onclick={handleAccountsSearch} 
                    class="slds-p-around_medium">
                </lightning-button>
            </lightning-layout-item>
            <lightning-layout-item padding="around-small">
                <br/>
                <lightning-button 
                    variant="destructive" 
                    icon-name="action:refresh" 
                    label="Reset Filters" 
                    onclick={handleFilterReset} 
                    class="slds-p-around_medium">
                </lightning-button>
            </lightning-layout-item>
        </lightning-layout>
    </div>
    <template lwc:if={listAccounts}>
        <lightning-card> 
            <lightning-datatable 
                key-field="Id"
                data={listAccounts}
                columns={columns}
                onrowaction={handleRowAction}
                hide-checkbox-column 
                show-row-number-column>
            </lightning-datatable>
        </lightning-card>   
    </template>
</template>

JavaScript:

import { LightningElement , wire} from 'lwc';
import ACCOUNT_OBJECT from '@salesforce/schema/Account';
import INDUSTRY_FIELD from '@salesforce/schema/Account.Industry';
import { getPicklistValues, getObjectInfo } from 'lightning/uiObjectInfoApi';
import fetchAccounts from '@salesforce/apex/AccountSearchController.fetchAccounts';
import { ShowToastEvent } from 'lightning/platformShowToastEvent';
import contactsPopUp from 'c/contactsPopUp';

export default class SampleLightningWebComponent extends LightningElement {
    
    accountName;
    listAccounts;
    selectedIndustries;
    optionsForIndustry;
    mapAccountIdContacts = {};
    industryLabel = 'Select Industry';
    defaultIndustries = [ 'Technology' ];
    columns = [ 
        { label: 'Name', fieldName: 'Name' }, 
        { label: 'Industry', fieldName: 'Industry' },
        { label: 'Type', fieldName: 'Type' },
        { label: 'Contacts Availability', fieldName: 'Availability' },
        { 
            label: 'Contacts', fieldName: 'ContactsURL', type: 'button',
            tooltip: 'View Contacts', iconName: 'standard:contact',
            typeAttributes: { 
                label: { fieldName: 'ContactsLabel' }, 
                variant: "base",
                name : 'ViewContacts'
            } 
        }
    ];

    connectedCallback() {

        this.selectedIndustries = this.defaultIndustries;

    }

    @wire( getObjectInfo, {objectApiName: ACCOUNT_OBJECT} )
    objectInfo;

    @wire(getPicklistValues, { 
        recordTypeId: '$objectInfo.data.defaultRecordTypeId', 
        fieldApiName: INDUSTRY_FIELD 
    } )
    wiredIndustryData( { error, data } ) {

        if ( data ) {        
            
            this.optionsForIndustry = [];
            let tempIndustryOptions = [];

            data.values.forEach( element => {

                let tempElement = {};
                tempElement.label = element.label;
                tempElement.value = element.value;

                if ( this.defaultIndustries.includes( tempElement.value ) ) {
                    tempElement.isSelected = true;
                } else {
                    tempElement.isSelected = false;
                }

                tempIndustryOptions.push( tempElement );

            } );
         
            this.optionsForIndustry = tempIndustryOptions;
            this.industryLabel = 'Industry (' + this.selectedIndustries.length + '/' + this.optionsForIndustry.length + ')';   

        } else if ( error ) {

            this.optionsForIndustry = [];
            console.error(
                error
            );

        }

    }

    handleChange( event ) {

        if ( event.target.label == 'Account Name' ) {

            this.accountName = event.target.value;

        } 

    }

    handleIndustryChange( event ) {
        
        let selectedIndustry = event.detail.value;
        let options = this.optionsForIndustry;
        let selectedOptions = this.selectedIndustries;

        options.forEach( function( tempElement ) {

            if ( tempElement.value == selectedIndustry ) {

                tempElement.isSelected = !tempElement.isSelected;

                if ( tempElement.isSelected === false ) {
                    selectedOptions = selectedOptions.filter( item => item !== selectedIndustry );
                } else {
                    selectedOptions.push( selectedIndustry );
                }

            }

        } );
        
        this.optionsForIndustry = [ ...options ];
        this.selectedIndustries = selectedOptions;
        this.industryLabel = 'Industry (' + this.selectedIndustries.length + '/' + this.optionsForIndustry.length + ')';

    }
    
    handleAccountsSearch() {

        fetchAccounts( { 
            strAccountName : this.accountName, 
            listSelectedIndustries : this.selectedIndustries
        } )
        .then( result => {

            console.log(
                'result is',
                JSON.stringify( result )
            );

            if ( result.length > 0 ) {

                let tempAccounts = [];
                let tempMapAccountIdContacts = {};

                result.forEach( function( tempAccountElement ) {

                    let tempAccount = {};
                    tempAccount.Id = tempAccountElement.Id;
                    tempAccount.Name = tempAccountElement.Name;
                    tempAccount.Industry = tempAccountElement.Industry;
                    tempAccount.Type = tempAccountElement.Type;

                    if ( tempAccountElement.Contacts ) {

                        tempAccount.Availability = 'Yes';
                        tempAccount.ContactsURL = tempAccountElement.Id;
                        tempAccount.ContactsLabel = 'View Contacts';
                        tempMapAccountIdContacts[ tempAccountElement.Id ] = { contacts: tempAccountElement.Contacts };

                    } else {

                        tempAccount.Availability = 'No';

                    }

                    tempAccounts.push( tempAccount );                    

                } );

                this.mapAccountIdContacts = tempMapAccountIdContacts;
                this.listAccounts = tempAccounts;

            } else {

                this.dispatchEvent(
                    new ShowToastEvent( {
                        title: 'Error!!',
                        message: 'No matching Accounts found',
                        variant: 'error',
                        mode: 'sticky'
                    } )
                );   
                this.listAccounts = undefined;

            }

        } )
        .catch( error => {

            this.dispatchEvent(
                new ShowToastEvent( {
                    title: 'Error!!',
                    message: JSON.stringify( error ),
                    variant: 'error',
                    mode: 'sticky'
                } )
            );     

        } )

    }

    handleFilterReset() {
        
        this.accountName = '';
        this.selectedIndustries = [ 'Technology' ];
        this.rebuildOptionsForIndustry();

    }

    rebuildOptionsForIndustry() {

        let tempIndustryOptions = [];
        this.optionsForIndustry.forEach( tempElement => {

            if ( this.selectedIndustries.includes( tempElement.value ) ) {
                tempElement.isSelected = true;
            } else {
                tempElement.isSelected = false;
            }

            tempIndustryOptions.push( tempElement );

        } );
            
        this.optionsForIndustry = [ ...tempIndustryOptions ];
        this.industryLabel = 'Industry (' + this.selectedIndustries.length + '/' + this.optionsForIndustry.length + ')';

    }

    handleRowAction( event ) {

        const selectedValue = event.detail.row.Id;
        const actionName = event.detail.action.name;
        console.log(
            'selectedValue is',
            JSON.stringify( selectedValue )
        );
        console.log(
            'actionName is',
            JSON.stringify( actionName )
        );

        if ( actionName === "ViewContacts" ) {
            
            console.log( 
                JSON.stringify( this.mapAccountIdContacts[ selectedValue ] )
            );
            const result = contactsPopUp.open( {
                size: 'large',
                description: 'Popup Dialog',
                listContacts: this.mapAccountIdContacts[ selectedValue ].contacts
            } );
            console.log(
                'result is',
                JSON.stringify( result )
            );

        }

    }

}

js-meta.xml:

<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>62.0</apiVersion>
    <isExposed>true</isExposed>
    <targets>
        <target>lightning__Tab</target>
    </targets>
</LightningComponentBundle>

Output:

Leave a Reply