Reusable LWCs to 10x your solution building speed.
messageService
: Lightning Message Service (LMS) simplified component messaging.SOQL Datatable
: Leverage SOQL to power your list views, related lists, and even Screen Flows.Collection Datatable
: Manage Record Collections variables in Screen Flows.- Design patterns leveraging both Aura and LWC to dynamically create dialogs (modals) for better UX.
- Launch Screen Flows dynamically inside a dialog (modal) from anywhere.
In this README:
This repo showcases the best defaults for creating rich, interactive, data-dense UIs using the following centerpieces:
lightning-datatable
from LWC.lightning:overlayLibrary
from Aura.lightning:flow
from Aura.Lightning Message Service
to stitch it all-together.
Salesforce has invested heavily into LWC
, Flow
and Screen Flow
and has given Architect Guidance around how to build scalable and flexible solutions now and into the future.
This repo builds on that guidance and pushes data-dense UI design to the next level with highly reusable, highly configurable components. These components have saved me thousands of developer hours and allowed me to pivot on a dime to meet the changing speed of business.
I hope they will help you do the same.
Component Name | Description | Component Type |
---|---|---|
messageService Example Code |
Use one API to communicate within or across both Aura and LWC technologies. Use this component instead of manually publishing / subscribing to Lightning Message Service (LMS).Provides a psuedo-namespacing property called boundary which can separate subscribers by string, recordId etc. |
LWC: - Service |
DialogService Example Code |
Provide LWCs access to lightning:overlayLibrary to create dialogs (modals) via LMS.Both Aura and LWCs can be created dynamically and injected as the dialog body. Both Aura's public attributes and LWC's @api properties can be passed in. |
Aura: - Service |
MessageServiceHandler Example Code |
Provides access to DialogService by handling the opendialog LMS event.This is a hidden component you need to place on the flexipage or utility bar (hidden, empty label). |
Aura: - Service - Utility Bar - Record Flexipage |
EventFooter Code |
Dynamic footer for lwc dialogs. Meant to be used by DialogService .Contains an instance of messageService listening for the closedialog LMS Event.Unfortunately, component.getReference() does not work on LWCs. Write your own action button in the dialog body. |
Aura: - Service |
ModalFooter Code |
Dynamic footer for aura dialogs. Meant to be used by DialogService .Connects a primary action on the target dialog body to the footer's main action via component.getReference() Enables writing functions directly on the dialog body and DialogService.modal() will connect it to a primary action. |
Aura: - Service |
FlowWrapper Example Code |
Helps with dynamic flow creation, for example, inside a dialog body created from DialogService .Can be used with dialogAutoCloser on the final screen to automatically close a Flow.See flowWizardLauncherExample |
Aura: - Service |
dialogAutoCloser Example Code |
Contains a progress bar and timer message (optional). Automatically publishes a closedialog LMS event and bubbles the same closedialog Custom Event when timer hits 0.Use uniqueBoundary to target a specific dialog to close if Tab-Focused Dialogs is Enabled |
LWC: - Service - Flow Screen |
soqlDatatable Example Code |
A SOQL powered list view. Meant to replace any related list / list view. Supports record context, in-line editing, configurable table/row actions, output of selected rows to Flow (or other LWCs) and more. See example for full features. |
LWC: - Service - App Flexipage - Record Flexipage - Flow Screen |
collectionDatatable Example Code |
Display Record Collections inside Flow Screens. Meant to mimic a related list / list view. Can be populated from a Flow's Get Records or soqlDatatable.selectedRows output. |
LWC: - Flow Screen |
Designed to ease the friction of inter-component (and technology) communication. This component is both the publisher and the subscriber to reduce implementation friction.
With that design, it's important to leverage the boundary
property to properly scope your event publisher/listeners.
Some components in this library, like soqlDatatable
, will generate a UUID to help scope payloads to its own child components (custom data type cells, dialogs etc).
This component uses Lightning Message Service
on OpenChannel__c
to message payloads
in a key
/ value
format as defined in OpenChannel__c
like this:
const payload = {
key: 'coolevent',
value: {
hello: 'world',
foo: 'bar'
}
}
this._messageService.publish(payload);
// or, my preferred method, this way
const payload = {
accountId: '12345'
}
this._messageService.publish({key: 'supercoolevent', value: payload});
And handled like this, composed on the template:
<c-message-service
boundary="sample_app_lwc"
oncoolevent={handleCoolEvent}
onsupercoolevent={handleSuperCoolEvent}
></c-message-service>
handleCoolEvent(event) {
console.log(event.detail.value.hello) // world
console.log(event.detail.value.foo) // bar
}
handleSuperCoolEvent(event) {
const payload = event.detail.value
console.log(payload.accountId) // 12345
}
This component doesn't need to subscribe to an event, it can be used for publish only:
<!-- No listeners, but has a boundary set for any publish() calls -->
<c-message-service boundary={recordId}></c-message-service>
... or
<!-- No listeners, no boundary set for any publish() calls -->
<c-message-service></c-message-service>
This component also provides public methods to Aura only APIs like overlayLibrary
.
For example, using .dialogService()
ultimately routes to DialogService.cmp
:
const dialogServicePayload = {
method: 'bodyModalLarge',
config: {
auraId: 'soql-datatable-example',
headerLabel: 'Dynamically Created SOQL Datatable',
component: 'c:soqlDatatable',
componentParams: {
isRecordBind: false,
recordId: this.recordId,
queryString: query
}
}
};
this._messageService.dialogService(dialogServicePayload);
messageService Specification
⠀
Attributes
name | type | access | required | default | description |
---|---|---|---|---|---|
boundary | string | public | no | Filter subscription messages like a namespace. e.g. recordId if you only want same components on same record flexipage to handle the publish.e.g. sample_app_lwc as reference among various components that share the same functionality.Enablement of APPLICATION_SCOPE like in this diagram is not currently enabled. |
Public Methods
name | arguments | description |
---|---|---|
dialogService | (payload ) |
payload is in the shape required by MessageServiceHandler . Examples:flowWizardLauncherExample lwcContactDatatable soqlDatatableLauncherExample |
notifyClose | Uses publishOpen to fire a closedialog LMS Event which will close any dialog opened by DialogService |
|
publish | (payload ) |
Leverages LMS's publish functionality.Defaults to no boundary .If boundary is set, all subscribers will require the same boundary . |
publishOpen | (payload ) |
Leverage LMS's publish functionality without boundary . Any subscriber can react to this event.// TODO Useful for closedialog unless this critical update is enabled.// TODO When a user can simultaneously open multiple dialogs in service console, it's better to set a boundary . |
forceRefreshView | Uses eval("$A.get('e.force:refreshView').fire();"); directly. |
|
notifySuccess | (title , message = null) |
Convenience function for ShowToastEvent |
notifyInfo | (title , message = null) |
Convenience function for ShowToastEvent |
notifySingleError | (title , error = '') |
Convenience function for ShowToastEvent .error object can be passed directly in, it will be reduced/parsed by c-utils.reduceError . |
This component is composed inside MessageServiceHandler
and provides it with the public methods for creating modals via Aura's overlayLibrary
.
Primarily used by messageService
for message publishing, MessageServiceHandler
receives the subscription and delegates to this component.
It is not recommended to use this component directly.
DialogService Specification
⠀
Attributes
name | type | access | required | default | description |
---|---|---|---|---|---|
overlayPromise | Object | public | no | Stores the returned overlay promise from overlayLibrary .If a callback is specified by the caller, this is returned. |
Public Methods
Arguments for this component are not in JS Object {}
notation so that they can be explicitly listed out in the component itself.
For that reason, it is recommended to use messageService
/ MessageServiceHandler
to call these functions.
name | arguments | description |
---|---|---|
showPopover | (body ,bodyParams ,referenceSelector ,cssClass ,callback ) |
No examples for this one yet. |
modal | (auraId ,headerLabel ,body ,bodyParams ,mainActionReference ,mainActionLabel ,callback ,) |
Compatible with Aura dialog bodies.body is the component name (Aura notation) to be created in a dialog.bodyParams are public attributes to be passed from the caller to the body.mainActionReference uses component.getReference to connect the primary action in ModalFooter to a function on the body to be created.This allows you to avoid writing a button specifically at the bottom of the body to be created. mainActionLabel changes the label of the primary action on ModalFooter .callback is optionally specified to return the overlayPromise if needed. Alternatively, listen for the dialogready LMS Event. |
modalLarge | (auraId ,headerLabel ,body ,bodyParams ,mainActionReference ,mainActionLabel ,callback ,isLargeModal = true ) |
Compatible with Aura dialog bodies. Same as modal , with wider dialog box using slds-modal_large |
bodyModal | (auraId ,headerLabel ,body ,bodyParams ,callback ) |
Compatible with LWC dialog bodies. Same as modal except without connectivity to a mainAction via component.getReference which doesn't work on LWCs, even with @api functions.Instead, a slim footer called EventFooter is created which is subscribing to the dialogclose event for closing the dialog.Write your own Cancel and Primary Action button on the dialog body that is dynamically being created. |
bodyModalLarge | (auraId ,headerLabel ,body ,bodyParams ,callback ,isLargeModal = true ) |
Compatible with LWC dialog bodies. Same as bodyModal , with wider dialog box using slds-modal_large |
As of early Summer 20, Lightning Message Service
requires rendering on the DOM to be connected.
Because of this limitation, this component is designed to be placed once on the utility bar (rendered, but hidden label) OR per flexipage.
The primary use case for this component is to parse the messageService.dialogService()
payload. It expects two properties:
const flowOrDialogServicePayload = {
method: 'bodyModal', // or bodyModalLarge, flowModal, flowModalLarge
config: {
<see flowWizardLauncherExample>
<or soqlDatatableLauncherExample>
}
}
This component is very simple which just listens and delegates to DialogService
.
It can easily be extended to include other Aura only APIs, such as lightning:workspaceAPI
.
<aura:component implements="lightning:utilityItem">
<c:DialogService aura:id="dialogService" />
<c:messageService aura:id="messageService" onopendialog="{! c.handleDialogService }" />
<c:singleton aura:id="singleton" />
</aura:component>
MessageServiceHandler Specification
⠀
Attributes
None
Public Methods
None
This component is designed to help launch flows dynamically, from any LWC click event.
This powers configurable flow actions (table and row) on soqlDatatable
by being dynamically created inside a dialog.
The component itself is very simple, as it's meant to be called via DialogService
which creates an instance of it:
// DialogService.executeDialogService()
...
if (payload.method.startsWith('flow')) {
flowModalConfig = {
auraId: 'flow-wizard-container',
headerLabel: payload.config.flowHeaderLabel,
component: 'c:FlowWrapper',
componentParams: {
flowApiName: payload.config.componentParams.flowApiName,
inputVariables: payload.config.componentParams.inputVariables
}
};
}
...
<aura:component>
<c:messageService aura:id="messageService" />
<aura:attribute name="flowApiName" type="String" access="PUBLIC" />
<aura:attribute name="inputVariables" type="Object[]" access="PUBLIC" />
<aura:handler name="init" value="{! this }" action="{! c.doInit }" />
<div class="slds-is-relative">
<lightning:flow aura:id="flow" onstatuschange="{! c.handleStatusChange }" />
</div>
</aura:component>
FlowWrapper Specification
⠀
Attributes
name | type | access | required | default | description |
---|---|---|---|---|---|
flowApiName | String | public | yes | Developer Name of the flow to be dynamically created by lightning:flow |
|
inputVariables | Object[] | public | yes | Array of inputs in flow's [{ name: 'flowVarName', type: 'String', value: 'my cool string value!' }] |
Public Methods
None
A simple component that counts down and auto closes a DialogService
opened dialog by sending a messageService
connected closedialog
event.
This is meant to be used with DialogService
when launching a Screen Flow as the final step.
However, there are a couple more ways to use it:
- As a visual countdown progress bar, handling the bubbled
closedialog
Custom Event by yourself. - Refreshing an instance of
soqlDatatable
by using theuniqueBoundary
andisRefreshTable
properties.- This sends a
boundary
scoped:refreshsoqldatatable
LMS event.
- This sends a
NOTE: It is recommended you provide this component a
uniqueBoundary
scoped to its caller, otherwise it may close more dialogs than intended if Tab-Focused Dialogs is enabled.
<template>
<c-message-service></c-message-service>
<lightning-layout horizontal-align="center" multiple-rows>
<lightning-layout-item flexibility="shrink">
{messageTemplate}
</lightning-layout-item>
<lightning-layout-item size="12">
<lightning-progress-bar value={progress}></lightning-progress-bar>
</lightning-layout-item>
</lightning-layout>
</template>
@api messageTemplate = 'Auto closing in {timer} seconds';
@api timer = 5;
...
renderedCallback() {
if (this._isRendered) {
return;
}
this._isRendered = true;
this._startProgressInterval();
this._startTimerInterval();
}
dialogAutoCloser Specification
⠀
Attributes
name | type | access | required | default | description |
---|---|---|---|---|---|
messageTemplate | String | public | no | Auto closing in {timer} seconds | Message to display to user while countdown is running |
timer | Number | public | no | 5 | Seconds until the component launches the closedialog LMS event |
Public Methods
None
Create a fully featured lightning-datatable
with just a SOQL String.
This component can be used on a Flexipage as a list view or a related list. This can even be used inside Screen Flows.
Since this is built on top of the lightning-datatable
base component, all the bells and whistles can be inherited.
The below example showcases how easy it is to create a soqlDatatable
right in the Lightning App Builder with the following query string:
SELECT Name, Email, Phone, LeadSource, Level__c, AccountId, Account.Type FROM Contact LIMIT 50
Using Record Context with $CurrentRecord
in the SOQL
⠀
$CurrentRecord
and $recordId
are special syntax that allows for merge-fields of current record data into the SOQL string. By using them, you can merge current record context as values in the WHERE
clause as follows:
// Find other Accounts similar to this Account's Industry
SELECT Name, Type, Website, Industry
FROM Account
WHERE Industry = $CurrentRecord.Industry
AND Id != $recordId
// Find related contacts with same MailingState as this Account's BillingState
SELECT Name, Email, MailingState, Account.BillingState
FROM Contact
WHERE AccountId = $recordId
AND MailingState = $CurrentRecord.BillingState
This uses Lightning Data Service (getRecord
) to retrieve and resolve the record values, so make sure your user(s) have FLS enabled for any fields you plan on using the $CurrentRecord
feature with.
All data types that can be SOQL-ed are supported for $CurrentRecord
.
Please submit issues to this repo if you find one that cannot be merged correctly.
Row Selection Events and Flow outputs
⠀
When this component's checkboxType
is configured to Multi
or Single
, the base datatable
emits a rowselection
event which can be handled by any parent LWC:
// datatable.js
case 'rowselection': {
this.dispatchEvent(
new CustomEvent('rowselection', {
detail: { selectedRows: this.selectedRows },
bubbles: true,
composed: true
})
);
break;
}
<c-soql-datatable
...
onrowselection={handleRowSelection}
...
></c-soql-datatable>
handleRowSelection(event) {
console.log(event.detail.selectedRows); // this.selectedRows from base datatable.js
}
This component also outputs selectedRows
and firstSelectedRow
to Flow screens as output variables. See the specification section for details.
Inline / Mass Inline Editing
⠀
Define which fields can be editable in a comma separated list in the Editable Fields
design attribute. For data types that are supported in the vanilla lightning-datatable
, such as date
, text
, number
, those are relied on as heavily as possible.
Note: All edits on
save
will be saved to database using Lightning Data ServiceupdateRecords
. Errors will be handled usinglightning-datatable
formatted error handling.
For data types such as picklist
and lookup
which are yet to be supported, this component provides custom data types as follows.
Picklist Custom Data Type
This custom data type is surfaced as customPicklist
. It always places a --None--
value, regardless of if your picklist is configured to always require a value. The save will fail and user will need to correct it to move on.
RecordType
restricted picklist values are supported with a limitation:
When using mass edit on a Picklist field for a Standard Object enabled with Record Types, it's possible to mass apply a value which does not belong on that table. This seems to be because Standard Object picklist fields do not have the
Restrict picklist to the values defined in the value set
option.
The actual picklist edit cell is a fork of the one authored by jlyon87 as found here
Lookup Custom Data Type
The custom LWC data type is surfaced as customLookup
.
Each soqlDatatable
can be have one defined Lookup Configuration (Datatable_Config__mdt
) to define lookup search behavior.
Because of a limitation with cmdt, the Type__c
on the parent Datatable_Config__mdt
must be Lookups
.
When using inline edit and lookup, there are two properties that are set as global defaults on Datatable_Lookup_Config__mdt
that help with the search results:
- Title: Name of the Record
- Subtitle: null
However, in this sample repo, they are overridden by the following settings:
Which produces this kind of search result:
The actual lookup edit cell is a fork of the one authored by jlyon87 as found here
Supported Features for all Custom Data Types
- Multi-line inline edit (aka mass-edit).
- Partial save across rows is supported.
- Error display user experience is aligned to native list views.
- If one row errors, all fields/columns for that row fail as well until all errors are resolved.
Unsupported / Roadmap Features
- Keyboard navigation.
- Pending lwc / aura issue investigation here.
- Geolocation fields must be queried with the
__Longitude__s
and__Latitude__s
(capital L). - Time data type is not yet supported for view or edit.
Column Sorting
⠀
Add a list of Field API names to the sortableFields
property to enable this feature. Parent notation (one level up) is supported.
Optionally, set default Sort Field
and Sort Direction
to have the asc/desc indicator automatically show when the table is initialized.
Multi-sort and filtering will not be supported.
Global search is on the roadmap (like regular list views)
Configurable Flow and LWC actions
⠀
Each soqlDatatable
can be have one defined Action Configuration (Datatable_Config__mdt
) to define both Table level (supporting multi / single select) and Row Level actions. This can be the same Datatable_Config__mdt
as used in the Lookup Configuration section.
Because of a limitation with cmdt, the Type__c
on the parent Datatable_Config__mdt
must be text of Actions
. For combined configs, use Actions; Lookups
.
Both LWCs (inside a dialog) and Screen Flows can be launched from either action type. The configuration is easier to explain in picture format:
Assign New Account - Flow Table Action
The button is configured to the SOQL_Datatable_Flow_Action_Update_Contacts_with_New_Account
Screen Flow.
soqlDatatable
sends the following inputVariables
to Flows.
All of the following must be implemented as variables if the Screen Flow backs an action, otherwise you will get an error.
Name | Type | Value |
---|---|---|
SelectedRows | SObject[] | Choose the correct Object type in a Record Collection. |
FirstSelectedRow | SObject | First Selected Row, choose the correct Object in a Record variable. |
UniqueBoundary | String | For dialogAutoCloser to refresh the table that opened the Screen Flow. |
SourceRecordId | String | The recordId of the page that the soqlDatatable is placed on. |
When the flow is done, it auto-closes using dialogAutoCloser
.
Note: Due to how data is constructed in
soqlDatatable
, you cannot use theSelectedRows
directly in aUpdate Records
. Always assign values you specifically want to update to a new Record Variable that is not an output ofsoqlDatatable
, which in this example isContactShell
/ContactToUpdate
.
Check Opportunities - LWC Table Action
This button configured to open the checkOpportunitiesExample
LWC.
Notice the public attributes, these are always supplied by soqlDatatable
when invoking an LWC.
<template>
<c-message-service boundary={uniqueBoundary}></c-message-service>
<template if:true={queryString}>
<c-soql-datatable query-string={queryString}></c-soql-datatable>
</template>
<template if:false={queryString}>
<div class="slds-align_absolute-center">
No Contacts Selected. Please choose contacts to view opportunities for.
</div>
</template>
</template>
...
@api uniqueBoundary;
@api selectedRows;
@api sourceRecordId;
queryString;
// private
_isRendered;
_messageService;
_accountIdSet = new Set();
connectedCallback() {
if (this.selectedRows && this.selectedRows.length) {
this.selectedRows.forEach(row => {
this._accountIdSet.add(`'${row.AccountId}'`);
});
}
if (this._accountIdSet.size > 0) {
let accountIds = Array.from(this._accountIdSet.keys());
this.queryString = convertToSingleLineString`
SELECT Account.Name, Name, Amount, CloseDate, StageName
FROM Opportunity
WHERE AccountId IN (${accountIds.join(',')})
ORDER BY Account.Name ASC
`;
}
}
...
Remove Phone - Flow Row Action
The button is configured to the SOQL_Datatable_Flow_Row_Action_Remove_Contact_Phone
Screen Flow.
This Screen Flow also auto-closes with dialogAutoCloser
.
Note: Due to how data is constructed in
soqlDatatable
, you cannot use theFirstSelectedRecord
directly in anUpdate Records
. Always assign values you specifically want to update to a new Record Variable that is not an output ofsoqlDatatable
, which in this example isContactToUpdate
.
Dynamic Creation via MessageService & DialogService
⠀
Dynamically create a soqlDatatable
when clicking the Launch a SOQL Datatable in a Dialog
button.
This is the psuedo-code of what happens:
button.js calls messageService.dialogService(payload)
=> button.js composed instance of messageService uses LMS to...
=> Another composed instance of messageService in MessageServiceHandler.cmp (label-less in utility bar)
=> CustomEvent opendialog is bubbled and handled in...
=> MessageServiceHandler.cmp component.finds()...
=> DialogService.cmp
=> DialogServiceController.js
=> $A.createComponent('c:soqlDatatable')
=> lightning:overlayLibrary
Here's the actual payload used in the above code flow:
handleOpenDialog() {
const query = convertToSingleLineString`
SELECT Title, Name, Email, Account.Name, Account.Type
FROM Contact
LIMIT 5
`;
const dialogServicePayload = {
method: 'bodyModalLarge',
config: {
auraId: 'soql-datatable-example',
headerLabel: 'Dynamically Created SOQL Datatable',
component: 'c:soqlDatatable',
componentParams: {
isRecordBind: false,
recordId: this.recordId,
queryString: query
}
}
};
this._messageService.dialogService(dialogServicePayload);
}
As you can see, it's possible to parameterize a payload back to Aura's $A.createComponent
API to instantiate a public properties against an LWC.
soqlDatatable Specification
Attributes
name | type | access | required | default | description |
---|---|---|---|---|---|
isRecordBind | Boolean | public | true | Only on Record Page. Use $CurrentRecord or $recordId in your SOQL query to use record context. User must have FLS access. | |
title | String | public | no | ||
showRecordCount | Boolean | public | false | ||
showRefreshButton | Boolean | public | false | ||
queryString | String | public | yes | Order of fields in the SOQL string determine order of columns. Parent (one level) relationships supported (e.g. Account.Type) | |
checkboxType | String | public | no | None | None, Multi, or Single (outputs radios). This allows the component to emit the rowselection event.For Screen Flows this populates the selectedRows and firstSelectedRow output variables. |
editableFields | String[] | public | no | Comma separated list of Field API names for inline editing. Does not support parent relationship (Account.Type). Saving writes to server. | |
sortableFields | String[] | public | no | Comma separated list of Field API names. Parent relationship is supported (e.g. Account.Type). | |
sortedBy | String | public | no | Single Field API Name. Parent relationship is supported (e.g. Account.Type). | |
sortedDirection | String | public | no | asc | |
actionConfigDevName | String | public | no | Not available on Flow Screen. Configure table and row actions with a record in Datatable_Config__mdt . |
|
lookupConfigDevName | String | public | no | Not available on Flow Screen. Configure inline edit lookup search behavior with a record in Datatable_Config__mdt . |
|
useRelativeMaxHeight | Boolean | public | false | Force table height to 60% of the vertical screen space. | |
selectedRows | SObject[] | public | Uses FlowAttributeChangeEvent to notify changes to Flow Screens. |
||
firstSelectedRow | SObject | public | Uses FlowAttributeChangeEvent to notify changes to Flow Screens. |
Public Methods
name | arguments | description |
---|---|---|
refreshTable | Refreshes the table (imperatively). |
This component is designed for use with Screen Flows to display tables of data from a Record Collection.
You can use Get Records
elements or selectedRows
from SOQL Datatable.
This was designed to provide data dense feedback to the user on what they're working on in a Screen Flow.
Manipulate a Record Collection
⠀
This example shows inline editing (single and mass) as well as how to handle saving edited records afterwards.
Show Selection in Collection Datatable
⠀
This Screen Flow uses the ability for soqlDatatable
to output a directly to collectionDatatable
.
Note: You can also assign
soqlDatatable
'sselectedRows
output to a Record Collection variable as well.
Inline / Mass Inline Editing
⠀
Define which fields can be editable in a comma separated list in the Editable Fields
design attribute. See soqlDatatable - Features and Examples for full details.
Note: All edits on
save
will not be saved to database. All error handling on edited rows must be handled by your flow manually.
collectionDatatable Specification
⠀
Attributes
All of the following are available as Flow output variables.
name | type | access | required | default | description |
---|---|---|---|---|---|
selectedRows | SObject[] | public | When checkboxType is set to Multi or Single , this has selected rows. |
||
firstSelectedRow | SObject | public | First selected row. | ||
editedRows | SObject[] | public | When editableFields is used AND the datatable is Saved , this outputs only edited rows. |
||
allRows | SObject[] | public | When editableFields is used AND the datatable is Saved , this outputs all rows. |
This unlocked package contains only the lib, no examples (recipes) that showcase their implementations. If you're working with this library for the first time, I recommend you install the "LWC Utils Recipes" in a sandbox after you install this.
Sandbox: https://test.salesforce.com/packaging/installPackage.apexp?p0=04t1Q000001QhOyQAK
PROD: https://login.salesforce.com/packaging/installPackage.apexp?p0=04t1Q000001QhOyQAK
This unlocked package must be installed after the above. This cannot be installed in PROD.
Sandbox: https://test.salesforce.com/packaging/installPackage.apexp?p0=04t1Q000001QhP3QAK
With the "LWC Utils Recipes", two sample apps (LWC Utils
and LWC Utils Console
) have been included to showcase various ways to implement the library.
There are also many example Flows
that have been set up as well.
After installation, please review the following:
Datatable_Config__mdt
Datatable_Lookup_Config__mdt
Datatable_Action_Config__mdt
For soqlDatatable
to successfully launch any configured Table / Row action (Flow and LWC) you must:
- Map a
Datatable_Config__mdt
that has aType__c
field that contains the textActions
. - Place
MessageServiceHandler
somewhere on the App / Record Flexipage or the Utility bar. This component launches dialogs/modals.
For soqlDatatable
inline editing of any Lookup data types, you must:
- Map a
Datatable_Config__mdt
that has aType__c
field that contains the textLookups
.Actions; Lookups
is a valid configuration. - Review the
Datatable_Lookup_Config.Default_Lookup_Config
and any necessary Object specific overrides.