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: