<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Oleksandra Todorenko</title>
    <description>The latest articles on DEV Community by Oleksandra Todorenko (@tdrnk).</description>
    <link>https://dev.to/tdrnk</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F981341%2F2e8e3160-7dd1-4f34-aead-d29a00cce30e.png</url>
      <title>DEV Community: Oleksandra Todorenko</title>
      <link>https://dev.to/tdrnk</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/tdrnk"/>
    <language>en</language>
    <item>
      <title>Salesforce Flow deactivation using Metadata API</title>
      <dc:creator>Oleksandra Todorenko</dc:creator>
      <pubDate>Wed, 31 Jan 2024 20:10:45 +0000</pubDate>
      <link>https://dev.to/tdrnk/salesforce-flow-deactivation-using-metadata-api-5dn4</link>
      <guid>https://dev.to/tdrnk/salesforce-flow-deactivation-using-metadata-api-5dn4</guid>
      <description>&lt;p&gt;Salesforce Flow is a powerful tool, offering declarative solutions for various business processes within the Salesforce ecosystem. While creating and updating flows is straightforward, deactivating an active flow presents its own set of challenges.&lt;/p&gt;

&lt;p&gt;Typically, one might assume that updating the &lt;code&gt;&amp;lt;status&amp;gt;&lt;/code&gt; tag in the flow XML file to a value indicating "Inactive" would deactivate the flow.&lt;br&gt;
According to the documentation, there are four possible status values:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Active&lt;/li&gt;
&lt;li&gt;Draft—In the UI, this status appears as Inactive.&lt;/li&gt;
&lt;li&gt;Obsolete—In the UI, this status appears as Inactive.&lt;/li&gt;
&lt;li&gt;InvalidDraft—In the UI, this status appears as Draft.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;However, using any of these values in the &lt;code&gt;flow-meta.xml&lt;/code&gt; file and deploying it to the org will not deactivate the flow.&lt;/p&gt;

&lt;p&gt;Let’s see the resolution of this tricky task of Salesforce Flow deactivation in the following example:&lt;/p&gt;

&lt;p&gt;I created a pretty simple flow that just makes a Chatter post on the Account record page when Billing Country is updated. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F73jcig1f23090av2a944.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F73jcig1f23090av2a944.png" alt="Active Salesforce flow" width="800" height="381"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can see, this flow is active.&lt;/p&gt;

&lt;p&gt;Retrieving this active flow from the org to the codebase reveals its XML structure. Here's a snippet:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;?xml version="1.0" encoding="UTF-8"?&amp;gt;
&amp;lt;Flow xmlns="http://soap.sforce.com/2006/04/metadata"&amp;gt;
   &amp;lt;actionCalls&amp;gt;
       &amp;lt;name&amp;gt;Post_Update_To_Chatter&amp;lt;/name&amp;gt;
       &amp;lt;label&amp;gt;Post Update To Chatter&amp;lt;/label&amp;gt;
       &amp;lt;locationX&amp;gt;50&amp;lt;/locationX&amp;gt;
       &amp;lt;locationY&amp;gt;431&amp;lt;/locationY&amp;gt;
       &amp;lt;actionName&amp;gt;chatterPost&amp;lt;/actionName&amp;gt;
       &amp;lt;actionType&amp;gt;chatterPost&amp;lt;/actionType&amp;gt;
       &amp;lt;flowTransactionModel&amp;gt;CurrentTransaction&amp;lt;/flowTransactionModel&amp;gt;
       &amp;lt;inputParameters&amp;gt;
           &amp;lt;name&amp;gt;text&amp;lt;/name&amp;gt;
           &amp;lt;value&amp;gt;
               &amp;lt;elementReference&amp;gt;ChatterMessageCountryChanged&amp;lt;/elementReference&amp;gt;
           &amp;lt;/value&amp;gt;
       &amp;lt;/inputParameters&amp;gt;
       &amp;lt;inputParameters&amp;gt;
           &amp;lt;name&amp;gt;subjectNameOrId&amp;lt;/name&amp;gt;
           &amp;lt;value&amp;gt;
               &amp;lt;elementReference&amp;gt;$Record.Id&amp;lt;/elementReference&amp;gt;
           &amp;lt;/value&amp;gt;
       &amp;lt;/inputParameters&amp;gt;
       &amp;lt;storeOutputAutomatically&amp;gt;true&amp;lt;/storeOutputAutomatically&amp;gt;
   &amp;lt;/actionCalls&amp;gt;
   &amp;lt;apiVersion&amp;gt;59.0&amp;lt;/apiVersion&amp;gt;
   &amp;lt;decisions&amp;gt;
       &amp;lt;name&amp;gt;CountryWasChanged&amp;lt;/name&amp;gt;
       &amp;lt;label&amp;gt;Country Was Changed&amp;lt;/label&amp;gt;
       &amp;lt;locationX&amp;gt;182&amp;lt;/locationX&amp;gt;
       &amp;lt;locationY&amp;gt;323&amp;lt;/locationY&amp;gt;
       &amp;lt;defaultConnectorLabel&amp;gt;Default Outcome&amp;lt;/defaultConnectorLabel&amp;gt;
       &amp;lt;rules&amp;gt;
           &amp;lt;name&amp;gt;PostToChatter&amp;lt;/name&amp;gt;
           &amp;lt;conditionLogic&amp;gt;and&amp;lt;/conditionLogic&amp;gt;
           &amp;lt;conditions&amp;gt;
               &amp;lt;leftValueReference&amp;gt;$Record.BillingCountry&amp;lt;/leftValueReference&amp;gt;
               &amp;lt;operator&amp;gt;NotEqualTo&amp;lt;/operator&amp;gt;
               &amp;lt;rightValue&amp;gt;
                   &amp;lt;elementReference&amp;gt;$Record__Prior.BillingCountry&amp;lt;/elementReference&amp;gt;
               &amp;lt;/rightValue&amp;gt;
           &amp;lt;/conditions&amp;gt;
           &amp;lt;conditions&amp;gt;
               &amp;lt;leftValueReference&amp;gt;$Record.BillingCountry&amp;lt;/leftValueReference&amp;gt;
               &amp;lt;operator&amp;gt;IsNull&amp;lt;/operator&amp;gt;
               &amp;lt;rightValue&amp;gt;
                   &amp;lt;booleanValue&amp;gt;false&amp;lt;/booleanValue&amp;gt;
               &amp;lt;/rightValue&amp;gt;
           &amp;lt;/conditions&amp;gt;
           &amp;lt;connector&amp;gt;
               &amp;lt;targetReference&amp;gt;Post_Update_To_Chatter&amp;lt;/targetReference&amp;gt;
           &amp;lt;/connector&amp;gt;
           &amp;lt;label&amp;gt;Post To Chatter&amp;lt;/label&amp;gt;
       &amp;lt;/rules&amp;gt;
   &amp;lt;/decisions&amp;gt;
   &amp;lt;environments&amp;gt;Default&amp;lt;/environments&amp;gt;
   &amp;lt;interviewLabel&amp;gt;Account Country Update Post To Chatter {!$Flow.CurrentDateTime}&amp;lt;/interviewLabel&amp;gt;
   &amp;lt;label&amp;gt;Account Country Update Post To Chatter&amp;lt;/label&amp;gt;
   &amp;lt;processMetadataValues&amp;gt;
       &amp;lt;name&amp;gt;BuilderType&amp;lt;/name&amp;gt;
       &amp;lt;value&amp;gt;
           &amp;lt;stringValue&amp;gt;LightningFlowBuilder&amp;lt;/stringValue&amp;gt;
       &amp;lt;/value&amp;gt;
   &amp;lt;/processMetadataValues&amp;gt;
   &amp;lt;processMetadataValues&amp;gt;
       &amp;lt;name&amp;gt;CanvasMode&amp;lt;/name&amp;gt;
       &amp;lt;value&amp;gt;
           &amp;lt;stringValue&amp;gt;AUTO_LAYOUT_CANVAS&amp;lt;/stringValue&amp;gt;
       &amp;lt;/value&amp;gt;
   &amp;lt;/processMetadataValues&amp;gt;
   &amp;lt;processMetadataValues&amp;gt;
       &amp;lt;name&amp;gt;OriginBuilderType&amp;lt;/name&amp;gt;
       &amp;lt;value&amp;gt;
           &amp;lt;stringValue&amp;gt;LightningFlowBuilder&amp;lt;/stringValue&amp;gt;
       &amp;lt;/value&amp;gt;
   &amp;lt;/processMetadataValues&amp;gt;
   &amp;lt;processType&amp;gt;AutoLaunchedFlow&amp;lt;/processType&amp;gt;
   &amp;lt;start&amp;gt;
       &amp;lt;locationX&amp;gt;56&amp;lt;/locationX&amp;gt;
       &amp;lt;locationY&amp;gt;0&amp;lt;/locationY&amp;gt;
       &amp;lt;connector&amp;gt;
           &amp;lt;targetReference&amp;gt;CountryWasChanged&amp;lt;/targetReference&amp;gt;
       &amp;lt;/connector&amp;gt;
       &amp;lt;object&amp;gt;Account&amp;lt;/object&amp;gt;
       &amp;lt;recordTriggerType&amp;gt;Update&amp;lt;/recordTriggerType&amp;gt;
       &amp;lt;triggerType&amp;gt;RecordAfterSave&amp;lt;/triggerType&amp;gt;
   &amp;lt;/start&amp;gt;
   &amp;lt;status&amp;gt;Active&amp;lt;/status&amp;gt;
   &amp;lt;textTemplates&amp;gt;
       &amp;lt;name&amp;gt;ChatterMessageCountryChanged&amp;lt;/name&amp;gt;
       &amp;lt;isViewedAsPlainText&amp;gt;true&amp;lt;/isViewedAsPlainText&amp;gt;
       &amp;lt;text&amp;gt;Attention! The Billing Country on this Account was changed from {!$Record__Prior.BillingCountry} to {!$Record.BillingCountry}&amp;lt;/text&amp;gt;
   &amp;lt;/textTemplates&amp;gt;
&amp;lt;/Flow&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Regardless of the status specified in the &lt;code&gt;&amp;lt;status&amp;gt;&lt;/code&gt; tag during deployment, the flow remains active.&lt;/p&gt;

&lt;p&gt;To resolve this, you need to retrieve the &lt;code&gt;.flowDefinition-meta.xml&lt;/code&gt; file associated with the flow. Within this file, set the &lt;code&gt;&amp;lt;activeVersionNumber&amp;gt;&lt;/code&gt; to 0.&lt;/p&gt;

&lt;p&gt;An example of how these files are structured in my project:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhguwroihqvt1f9hh6hem.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhguwroihqvt1f9hh6hem.png" alt="Structure in codebase" width="800" height="161"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here's how the file structure appears after retrieval:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;?xml version="1.0" encoding="UTF-8"?&amp;gt;
&amp;lt;FlowDefinition xmlns="http://soap.sforce.com/2006/04/metadata"&amp;gt;
   &amp;lt;activeVersionNumber&amp;gt;2&amp;lt;/activeVersionNumber&amp;gt;
&amp;lt;/FlowDefinition&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And here's the adjustment to deactivate the flow before deployment:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;?xml version="1.0" encoding="UTF-8"?&amp;gt;
&amp;lt;FlowDefinition xmlns="http://soap.sforce.com/2006/04/metadata"&amp;gt;
   &amp;lt;activeVersionNumber&amp;gt;0&amp;lt;/activeVersionNumber&amp;gt;
&amp;lt;/FlowDefinition&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once deployed, the flow is successfully deactivated.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjzrvc9s5d1a5nzohv7s1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjzrvc9s5d1a5nzohv7s1.png" alt="Salesforce flow deactivated" width="800" height="334"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This simple yet effective approach offers a solution to the challenge of deactivating Salesforce Flows programmatically. Share your insights and alternative methods for flow deactivation in the comments below, and let's enrich our knowledge together!&lt;/p&gt;

</description>
      <category>salesforce</category>
      <category>flow</category>
      <category>metadataapi</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Mass Profile Update in Salesforce. A Quick Step-by-Step Guide</title>
      <dc:creator>Oleksandra Todorenko</dc:creator>
      <pubDate>Thu, 30 Nov 2023 21:50:38 +0000</pubDate>
      <link>https://dev.to/tdrnk/mass-profile-update-in-salesforce-a-quick-step-by-step-guide-5bf2</link>
      <guid>https://dev.to/tdrnk/mass-profile-update-in-salesforce-a-quick-step-by-step-guide-5bf2</guid>
      <description>&lt;p&gt;Managing profiles and permissions efficiently is a must for Salesforce developers to keep accesses up-to-date and prevent data leakage. If in your Salesforce organization most of the permissions are set in profiles, not permission sets, you may face the task of updating many profiles for some specific permission. And the more profiles you need to update, the more time it will take. Mass-updating profiles saves significant time and ensures consistent configurations across multiple profiles. It’s an efficient way to bulkify and optimize your work within the scope of standard Salesforce functionality.&lt;br&gt;
Now, let's dive into the steps:&lt;/p&gt;

&lt;h2&gt;
  
  
  Navigate to the Profiles Page
&lt;/h2&gt;

&lt;p&gt;Begin by logging into your Salesforce organization and accessing the Setup menu. In the Quick Find box, type "Profiles" and select the "Profiles" option.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3zbveehop9rze2x2sekz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3zbveehop9rze2x2sekz.png" alt="Profiles page"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Create a Targeted List View
&lt;/h2&gt;

&lt;p&gt;To be able to update several profiles at the same time, we need to create a profile list view. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7ose7qizcsijrkb519e2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7ose7qizcsijrkb519e2.png" alt="Create List View"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This view can be filtered based on profile properties, such as displaying only custom profiles. If you are creating a list view only for mass profile updates, I suggest filtering profiles to display only custom ones - only custom profiles can be edited.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx3djso4mx0p63teeg79q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx3djso4mx0p63teeg79q.png" alt="List view filters"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Also, add all the fields that you need to mass update. In my example, it will be a field for Opportunity deletion and Contact deletion. Then save this list view.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6bxv91qmfrwtb14tc8ve.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6bxv91qmfrwtb14tc8ve.png" alt="Fields to display"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Select list view and profiles for editing
&lt;/h2&gt;

&lt;p&gt;Select your list view from the dropdown.&lt;br&gt;
Then select all the profiles for which you want to mass update the permission.&lt;br&gt;
Also, you can choose all the profiles by selecting the first checkbox.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4ancoc49briz4tkfsjkk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4ancoc49briz4tkfsjkk.png" alt="Profiles selected"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Double-Click the Permission to Edit
&lt;/h2&gt;

&lt;p&gt;Double-click on the permission you want to modify. Whether you're editing one or multiple profiles, this action opens a convenient dialog box for quick adjustments.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw6wfifw5play5ruqjo7e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw6wfifw5play5ruqjo7e.png" alt="Dialog opened"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Modify Permissions in the Dialog Box
&lt;/h2&gt;

&lt;p&gt;Within the dialog box, enable or disable the permission as needed. &lt;/p&gt;

&lt;h2&gt;
  
  
  Handle Cascading Changes
&lt;/h2&gt;

&lt;p&gt;Pay attention to the cascading changes that may affect other permissions. The dialog box will highlight any affected permissions, ensuring you're aware of the broader impact.&lt;/p&gt;

&lt;h2&gt;
  
  
  Save Changes
&lt;/h2&gt;

&lt;p&gt;To apply changes across multiple profiles, select "All n selected records" (where n is the number of profiles you've chosen). Complete the process by clicking the "Save" button.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq7fwdl4987hbf2krhe2v.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq7fwdl4987hbf2krhe2v.png" alt="Profiles are mass updated"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;By following this guide, you can seamlessly update permissions across multiple profiles.&lt;/p&gt;

&lt;p&gt;Remember, utilizing list views with targeted filters and displayed fields enhances your profile management capabilities, allowing you to complete your tasks faster. Happy optimizing!&lt;/p&gt;

</description>
      <category>salesforce</category>
      <category>profile</category>
      <category>salesforceadministration</category>
      <category>massprofileupdate</category>
    </item>
    <item>
      <title>8 Tips for Pixel-Perfect Email Templates in Salesforce</title>
      <dc:creator>Oleksandra Todorenko</dc:creator>
      <pubDate>Tue, 01 Aug 2023 12:38:01 +0000</pubDate>
      <link>https://dev.to/tdrnk/8-tips-for-pixel-perfect-email-templates-in-salesforce-359p</link>
      <guid>https://dev.to/tdrnk/8-tips-for-pixel-perfect-email-templates-in-salesforce-359p</guid>
      <description>&lt;p&gt;Creating Lightning Email Templates in Salesforce is essential for Sales Managers and Marketing professionals to streamline communication and maintain consistent branding. Ensuring that recipients receive emails with the expected style and appearance is crucial for a seamless and professional experience. Let's explore the best practices to achieve this goal and deliver effective email communication to our audience.&lt;/p&gt;

&lt;h2&gt;
  
  
  Validate in different Mail clients
&lt;/h2&gt;

&lt;p&gt;Once you've prepared a template in Salesforce and tested it in Gmail, take a moment before saving it as the final version. Some mail clients may not support all CSS properties, leading to unexpected appearances for recipients. Notably, the Outlook app for Windows lacks support for numerous HTML elements and CSS properties, such as &lt;code&gt;max-width&lt;/code&gt;, &lt;code&gt;border-radius&lt;/code&gt;, styles on &lt;code&gt;p&lt;/code&gt;, &lt;code&gt;div&lt;/code&gt; elements, etc. &lt;br&gt;
Also, there are platforms where you can validate the appearance of your email in different versions, platforms and devices, just by inserting its HTML template. Unfortunately, I found only paid solutions (Litmus, Email on Acid). Please share in the comments if you can recommend other platforms, especially free ones :)&lt;/p&gt;
&lt;h2&gt;
  
  
  Use Email Template Builder
&lt;/h2&gt;

&lt;p&gt;Salesforce's Email Template Builder allows easy creation of email templates with a drag-and-drop functionality. To enable this feature, users need &lt;code&gt;Access Drag-and-Drop Content Builder&lt;/code&gt; permission. Once granted, they can click the 'Edit in Builder' button to get started.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwfnw8qpa53xf04tnoqd8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwfnw8qpa53xf04tnoqd8.png" alt="Edit in builder button"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Despite some limitations, the Email Template Builder allows the insertion of HTML code, images, text areas, and columns, making it a handy solution for quick email template building.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9lu4uvmxmjccrb6tvf2z.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9lu4uvmxmjccrb6tvf2z.png" alt="Email Builder in Salesforce"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Table structure
&lt;/h2&gt;

&lt;p&gt;To ensure your email's appearance aligns with your expectations, it's recommended to structure emails using tables. Although this approach involves more complex code than using div elements, it guarantees compatibility across all mail clients. Make sure to apply all styles at the &lt;code&gt;&amp;lt;td&amp;gt;&lt;/code&gt; level, as styles set elsewhere may not be supported in some browsers and mail clients.&lt;/p&gt;
&lt;h2&gt;
  
  
  Duplicate style properties
&lt;/h2&gt;

&lt;p&gt;Certain CSS properties, like &lt;code&gt;align&lt;/code&gt;, &lt;code&gt;vertical-align&lt;/code&gt;, &lt;code&gt;width&lt;/code&gt;, &lt;code&gt;height&lt;/code&gt;, etc., should be defined twice. Include them in the CSS style for most mail clients and separately on the &lt;code&gt;&amp;lt;td&amp;gt;&lt;/code&gt; element for mail clients like Outlook.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;td style="width:150px; height: 100%; vertical-align: middle" width="150" height="100%" valign="middle"&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that for properties with px values, we write only the number (e.g., &lt;code&gt;width="150"&lt;/code&gt;). For percent values, we add a percent sign.&lt;/p&gt;

&lt;h2&gt;
  
  
  Use only supported properties
&lt;/h2&gt;

&lt;p&gt;Keep in mind that even popular mail clients may have limited or no support for certain HTML or CSS properties. Be cautious when using elements and properties, ensuring they are supported in your recipients' mail clients. You can check each property's support for the most popular email clients on the &lt;a href="https://www.caniemail.com/" rel="noopener noreferrer"&gt;CanIEmail&lt;/a&gt; website.&lt;/p&gt;

&lt;p&gt;For example, the &lt;code&gt;border-radius&lt;/code&gt; property that creates rounded corners on buttons:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4mnb7yqhhevgpt1p397p.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4mnb7yqhhevgpt1p397p.png" alt="border-radius in CanIEmail"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Avoid VML in your templates
&lt;/h2&gt;

&lt;p&gt;While creating adaptive email templates, you might come across VML (Vector Markup Language), a code format used to create graphics and visual elements, which allows adding interactive elements and custom background images to make email campaigns more engaging. However, it's important to note that VML is not supported in Salesforce email templates. If you attempt to use VML, it will be deleted when you save the email template. Therefore, it's best to avoid VML and explore alternative solutions to achieve your desired design and interactivity.&lt;/p&gt;

&lt;h2&gt;
  
  
  Simplify editing with a developer console
&lt;/h2&gt;

&lt;p&gt;While making style adjustments in Salesforce's email templates, you can switch views by clicking the Source button to see the HTML code. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnkca042xv0fdq5k0fy0u.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnkca042xv0fdq5k0fy0u.png" alt="Source button"&gt;&lt;/a&gt;&lt;br&gt;
However, to view applied style changes in real-time, use the built-in browser's Developer Console. Any changes made there will be applied to the email template when saving and won't be overwritten by styles set in the Source tab.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj1qwf683u7o38c6yug16.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj1qwf683u7o38c6yug16.gif" alt="Dev console save"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Disable text editing extensions
&lt;/h2&gt;

&lt;p&gt;If you use text editing extensions in your browser, such as Grammarly or QuillBot, be mindful that they may add elements or logos to your email template automatically. In Salesforce these elements can be saved as a part of your email template and your recipients will receive them by mistake. Ensure that the final version of your email template doesn't include any extra symbols, images, or unexpected elements.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;To sum up, Salesforce allows an extensive functionality in using and creating email templates. Just sometimes you need to know its limitations and features to be like a Pro.&lt;br&gt;
Have some valuable insights or nifty tricks for working with Salesforce Email Templates? Drop them in the comments below, and let's exchange our knowledge!&lt;/p&gt;

&lt;p&gt;If you've found this article informative and useful, I'd love to connect with you on &lt;a href="https://www.linkedin.com/in/tdrnk/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;. Building a network of like-minded Salesforce enthusiasts is always exciting. Feel free to reach out with any questions or feedback about the article. I'm here to engage in a conversation and provide further assistance. Let's connect and continue learning and growing together in the Salesforce community!&lt;/p&gt;

</description>
      <category>salesforce</category>
      <category>emailtemplate</category>
      <category>salesforcedevelopment</category>
      <category>salesforceadministration</category>
    </item>
    <item>
      <title>Resolving UnitPrice Recalculation for OpportunityLineItem Update</title>
      <dc:creator>Oleksandra Todorenko</dc:creator>
      <pubDate>Tue, 06 Jun 2023 07:38:11 +0000</pubDate>
      <link>https://dev.to/tdrnk/resolving-unitprice-recalculation-for-opportunitylineitem-update-533j</link>
      <guid>https://dev.to/tdrnk/resolving-unitprice-recalculation-for-opportunitylineitem-update-533j</guid>
      <description>&lt;p&gt;In Salesforce, the Opportunity Product standard object (OpportunityLineItem) serves as the foundation for many functionalities. While custom objects and fields generally exhibit consistent behavior, standard objects can have more complex logic with additional dependencies and limitations. &lt;/p&gt;

&lt;p&gt;Recently, I encountered an unusual behavior related to the OpportunityLineItem's UnitPrice field recalculation. This recalculation occurs when a record is updated indirectly, outside of the Salesforce Lightning or Classic record pages. It may happen through updates made via Apex, Automation Tools, or Extensions (such as Salesforce Inspector or similar tools).&lt;/p&gt;

&lt;p&gt;The behavior specifically revolves around the Quantity and UnitPrice fields, and how the UnitPrice is recalculated when the Quantity is modified without explicitly querying the UnitPrice field. In this article, I will share my observations of this behavior and provide a workaround to ensure accurate updates while preserving the original UnitPrice value.&lt;/p&gt;

&lt;h2&gt;
  
  
  Example
&lt;/h2&gt;

&lt;p&gt;Let's examine a scenario to better understand this behavior:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzsfjzbix5na74swa3201.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzsfjzbix5na74swa3201.png" alt="Initial values"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Consider an Opportunity Product record with the following initial data:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Sales Price (API name UnitPrice): 100,000 EUR&lt;/li&gt;
&lt;li&gt;Total Price: 100,000 EUR&lt;/li&gt;
&lt;li&gt;Quantity: 1&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We will perform updates on the Quantity field, setting it to a value of '2', and observe the outcomes in different scenarios.&lt;/p&gt;

&lt;h3&gt;
  
  
  Update from the Lightning Record Page
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5gelr47ob5dwnbomvbyp.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5gelr47ob5dwnbomvbyp.gif" alt="lightning update"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this case, the behavior is as expected. The Quantity is updated to '2', the Sales Price remains unchanged, and the Total Price becomes 200,000 EUR, which is logically consistent.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc6xu9im5tm987al36bq0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc6xu9im5tm987al36bq0.png" alt="After lightning update"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Update from Apex
&lt;/h3&gt;

&lt;p&gt;Let's update this record using Anonymous Apex with the following code snippet:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;OpportunityLineItem oli = [SELECT Id, Quantity FROM OpportunityLineItem WHERE Id = '00k6800000c3THrAAM']; //Id of selected OLi
oli.Quantity = 2;
update oli;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc1ceifeilo7un6e0ya3n.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc1ceifeilo7un6e0ya3n.gif" alt="Apex update no UnitPrice"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this scenario, we observe that the Total Price remains the same, but the Sales Price becomes two times smaller, like following the formula Total Price/Quantity.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why UnitPrice gets recalculated
&lt;/h2&gt;

&lt;p&gt;Upon investigating this unusual behavior, I discovered that these fields are interdependent based on the following formula:&lt;br&gt;
&lt;code&gt;TotalPrice = (UnitPrice * Quantity) * Discount&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;When only the Quantity field is updated without querying the UnitPrice field, the system recalculates the UnitPrice as TotalPrice divided by (Quantity * Discount).&lt;/p&gt;
&lt;h2&gt;
  
  
  Workaround
&lt;/h2&gt;

&lt;p&gt;To overcome this unexpected UnitPrice recalculation, I found a workaround that involves explicitly querying the UnitPrice field. By doing so, we can retain the original UnitPrice value while updating the Quantity accurately.&lt;/p&gt;

&lt;p&gt;Here's an example implementation, along with a video demonstration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;OpportunityLineItem oli = [SELECT Id, UnitPrice, Quantity FROM OpportunityLineItem WHERE Id = '00k6800000c3THrAAM'];
oli.Quantity = 2;
update oli;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqmtvse2jz0bj8u5dgqmm.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqmtvse2jz0bj8u5dgqmm.gif" alt="Quantity update with UnitPrice"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can see, even without directly updating the UnitPrice field, just by adding it to the query, we achieve the expected behavior and avoid unnecessary recalculations.&lt;/p&gt;

&lt;p&gt;If you have any alternative workarounds in mind or are aware of other action sequences where field recalculation may occur, please feel free to share them in the comments section. Your insights and contributions are greatly appreciated!&lt;/p&gt;

</description>
      <category>salesforce</category>
      <category>opportunitylineitem</category>
      <category>unitprice</category>
      <category>opportunityproduct</category>
    </item>
    <item>
      <title>Make Salesforce Emailing Effortless: Customize SendEmail Action in 3 Simple Steps</title>
      <dc:creator>Oleksandra Todorenko</dc:creator>
      <pubDate>Thu, 13 Apr 2023 08:58:22 +0000</pubDate>
      <link>https://dev.to/tdrnk/make-salesforce-emailing-effortless-customize-sendemail-action-in-3-simple-steps-1702</link>
      <guid>https://dev.to/tdrnk/make-salesforce-emailing-effortless-customize-sendemail-action-in-3-simple-steps-1702</guid>
      <description>&lt;p&gt;If you want to streamline your email communication with customers and colleagues in Salesforce, you may consider overriding the standard SendEmail action with predefining certain fields, such as To, CC, BCC, subject, body, email template and others. Especially, it would be a great time saver if Salesforce users are still doing it by themselves every time when Email should be sent. &lt;/p&gt;

&lt;p&gt;By doing this, we can save time, increase productivity, ensure accuracy, maintain compliance, and personalize communication. A great benefit is this can be done without any coding, making it a simple, quick and accessible solution for Salesforce Admins who want to optimize their workflow. &lt;/p&gt;

&lt;h2&gt;
  
  
  When and why you should think about overriding
&lt;/h2&gt;

&lt;p&gt;There are several main cases where overriding the standard SendEmail action with a custom action that predefines certain fields can be useful for Salesforce Admins:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Consistency and accuracy:&lt;/strong&gt; By predefining fields like the recipient, subject, and body, you can ensure that all emails sent from Salesforce are consistent and accurate. This can help to maintain a professional image and avoid errors or misunderstandings.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Efficiency and productivity:&lt;/strong&gt; Predefining fields in a custom SendEmail action can save time and increase productivity, as users don't have to manually enter all the details each time they send an email. This can be particularly useful for sales teams or customer service representatives who need to send multiple emails per day.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Compliance and governance:&lt;/strong&gt; In some industries or organizations, there may be strict regulations or policies around email communication. By predefining fields in a custom SendEmail action, you can ensure that all emails sent from Salesforce comply with these regulations and policies.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Customization and personalization:&lt;/strong&gt; By predefining fields like the email template or the CC recipients, you can customize and personalize your emails to better suit your audience. This can help to build stronger relationships with customers and colleagues.&lt;/p&gt;

&lt;h2&gt;
  
  
  A step-by-step guide to Override Standard SendEmail Action
&lt;/h2&gt;

&lt;p&gt;Unfortunately, the standard Salesforce SendEmail action is not editable, which means that we cannot set field values exactly as we want in the standard action. &lt;br&gt;
However, we can create a custom action that will replace the standard one and allow us to predefine certain fields. Here are 3 simple steps to achieve it:&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: Create a Custom Action
&lt;/h3&gt;

&lt;p&gt;Go to the Object Manager and select the object for which you want to create the custom SendEmail action. In this example, we'll use the Opportunity object.&lt;/p&gt;

&lt;p&gt;Click on the "Buttons, Links, and Actions" tab and then click "New Action". Select "Send Email" as the action type and enter a label and name for your custom action.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw9om7mrffav9h40l5a1l.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw9om7mrffav9h40l5a1l.png" alt="created custom SendEmail"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2: Set predefined fields
&lt;/h3&gt;

&lt;p&gt;Under Action Details, you can define the predefined fields for your custom SendEmail action.&lt;/p&gt;

&lt;p&gt;Example of fields that I created you may see here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6grpqf1ahjirw0lu6wbw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6grpqf1ahjirw0lu6wbw.png" alt="Predefined fields example"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here is a list of fields that can be predefined, with their API names and short description:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu0vkuk4zvsii8x82ili8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu0vkuk4zvsii8x82ili8.png" alt="Fields to predefine"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;BCC&lt;/strong&gt; (&lt;code&gt;BccAddress&lt;/code&gt;): email addresses that will be BCC'd on the email (hidden from other recipients)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;BCC Recipients&lt;/strong&gt; (&lt;code&gt;BccIds&lt;/code&gt;): the User or Lead/Contact who will be BCC'd on the email&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CC&lt;/strong&gt; (&lt;code&gt;CcAddress&lt;/code&gt;): the email address that will be CC'd on the email&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CC Recipients&lt;/strong&gt; (&lt;code&gt;CcIds&lt;/code&gt;): the User or Lead/Contact who will be CC'd on the email&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Email Template&lt;/strong&gt; (&lt;code&gt;EmailTemplate&lt;/code&gt;): the email template that will be used for the email content&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;External Id&lt;/strong&gt; (&lt;code&gt;ExternalId&lt;/code&gt;): an optional external ID field that can be used for integration purposes&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;From&lt;/strong&gt; (&lt;code&gt;ValidatedFromAddress&lt;/code&gt;): the email address that the email will appear to be sent from. This must be a verified email address in your organisation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Html Body&lt;/strong&gt; (&lt;code&gt;HtmlBody&lt;/code&gt;): the HTML version of the email content&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;In Reply To&lt;/strong&gt; (&lt;code&gt;InReplyTo&lt;/code&gt;): the Message-ID of the email being replied to. This is used to thread email conversations.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Message Id&lt;/strong&gt; (&lt;code&gt;MessageId&lt;/code&gt;): the Message-ID of the email. This is used to thread email conversations.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Primary Who&lt;/strong&gt; (&lt;code&gt;Who&lt;/code&gt;): the primary Lead/Contact/User that the email is being sent to&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;References&lt;/strong&gt; (&lt;code&gt;References&lt;/code&gt;): the Message-ID of the email being replied to and other Message-IDs in the conversation. This is used to thread email conversations.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Related To&lt;/strong&gt; (&lt;code&gt;RelatedTo&lt;/code&gt;): the record that the email is related to. This is typically used when sending emails related to a specific record in Salesforce.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Subject&lt;/strong&gt; (&lt;code&gt;Subject&lt;/code&gt;): the subject line of the email&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Text Body&lt;/strong&gt; (&lt;code&gt;TextBody&lt;/code&gt;): the plain text version of the email content&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;To&lt;/strong&gt; (&lt;code&gt;ToAddress&lt;/code&gt;): the email address that the email will be sent to&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;To Recipients&lt;/strong&gt; (&lt;code&gt;ToIds&lt;/code&gt;): the User or Lead/Contact who will receive the email&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Step 3: Replace Quick Action on the layout
&lt;/h3&gt;

&lt;p&gt;Once you have defined your CustomEmail action, you need to add it to the Object’s page layout. Go to the page layout editor for the desired object, in my case it’s Opportunity, select the "Mobile &amp;amp; Lightning Actions" section, and drag your custom SendEmail action to the section. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnw36vqwgrclk3jq1j9rf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnw36vqwgrclk3jq1j9rf.png" alt="Custom SendEmail on layout"&gt;&lt;/a&gt;&lt;br&gt;
You need also to remove the standard SendEmail action from the section. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fojyalpd8qjycvxtc21jg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fojyalpd8qjycvxtc21jg.png" alt="Standard SendEmail on layout"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It is necessary as then exactly custom SendEmail action will be launched when clicking on the Email activity button. All the others SendEmail actions will be accessible by clicking the arrow from the right side.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhoywzv9ctz6zr5g7jn2s.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhoywzv9ctz6zr5g7jn2s.png" alt="arrow down"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Result
&lt;/h2&gt;

&lt;p&gt;And that’s it! The predefined fields you defined in Step 2 should now be populated with the values you specified, allowing you to quickly and easily send an email without having to manually enter all the details.&lt;/p&gt;

&lt;p&gt;Let's compare standard and custom SendEmail actions:&lt;br&gt;
Standard:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv9aibstrlcbpuel31084.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv9aibstrlcbpuel31084.png" alt="Standard SendEmail"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Custom:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feqtae1akhtxwr6ccfmut.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feqtae1akhtxwr6ccfmut.png" alt="Custom SendEmail"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Standard Salesforce SendEmail action cannot be customized, but don't let that limit your ability to streamline your email communication processes. By creating a custom Send Email action and predefining fields, you can save your users time and effort. This is especially useful if you frequently send emails to a specific group of people, or if you want to ensure that certain fields are always filled out correctly.&lt;/p&gt;

&lt;p&gt;Whether you're a Salesforce admin or a developer, this customization can be a great way to enhance your organization's productivity and make your users' lives easier.&lt;/p&gt;

&lt;p&gt;If you have any questions or comments, please don't hesitate to reach out here or in &lt;a href="https://www.linkedin.com/in/tdrnk/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt; – I'm always happy to connect with fellow Salesforce enthusiasts!&lt;/p&gt;

</description>
      <category>salesforce</category>
      <category>sendemail</category>
      <category>salesforceadministration</category>
      <category>customactions</category>
    </item>
    <item>
      <title>Subscribing to Salesforce Platform Events in Workbench: A Step-by-Step Guide</title>
      <dc:creator>Oleksandra Todorenko</dc:creator>
      <pubDate>Sat, 28 Jan 2023 18:44:31 +0000</pubDate>
      <link>https://dev.to/tdrnk/subscribing-to-salesforce-platform-events-in-workbench-a-step-by-step-guide-2p45</link>
      <guid>https://dev.to/tdrnk/subscribing-to-salesforce-platform-events-in-workbench-a-step-by-step-guide-2p45</guid>
      <description>&lt;p&gt;Salesforce platform events are a powerful tool for real-time data processing within the Salesforce ecosystem. Using platform events, you can easily transfer data of different types (with customizable fields) using a publish-subscribe model, where a sender (publisher) sends an event and one or more receivers (subscribers) receive the event. &lt;br&gt;
Unlike sObjects, platform events can’t be queried using SOQL or SOSL, that is why we can use Workbench to subscribe to the specific Platform Event and track its validity. &lt;/p&gt;

&lt;p&gt;In this article, we’ll discuss how to create platform events, their specifics and will subscribe to one of them using Workbench to see what data is received.&lt;/p&gt;
&lt;h2&gt;
  
  
  Table of Content
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Creating platform event&lt;/li&gt;
&lt;li&gt;Publishing platform event&lt;/li&gt;
&lt;li&gt;Subscribing to the platform event using Workbench&lt;/li&gt;
&lt;li&gt;Demo&lt;/li&gt;
&lt;li&gt;Summary&lt;/li&gt;
&lt;li&gt;Let's connect!&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Creating platform event
&lt;/h2&gt;

&lt;p&gt;To demonstrate how platform events work, let’s create an event that will be published when the Contact record changes (in the trigger) to let subscribers know that the contact has changed his job (Title or Department fields are changed). &lt;br&gt;
To create a platform event, go to Setup -&amp;gt; Platform Events -&amp;gt; New Platform Event.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6b2b1v0cq1e439sugiiz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6b2b1v0cq1e439sugiiz.png" alt="Platform events in setup" width="800" height="433"&gt;&lt;/a&gt;&lt;br&gt;
Here is an example of a created platform event. Please pay attention to the fields - we can add custom fields of different data types (Checkbox, Date, Date/Time, Number, Text, Text Area Long). &lt;br&gt;
In our case, we need the following custom fields: Contact Company (AccountId), ContactId, Contact Name, Department and Job Title. These fields will be filled in the Contact Trigger.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkui57m2mftzn1nrl174u.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkui57m2mftzn1nrl174u.png" alt="Created platform event" width="800" height="311"&gt;&lt;/a&gt;&lt;br&gt;
Note: don’t forget to provide the required permissions to the users who will publish and subscribe to the events. It can be done by adding an object assignment to the custom profile or to the permission set that will be assigned to the specific users.&lt;/p&gt;
&lt;h2&gt;
  
  
  Publishing platform event
&lt;/h2&gt;

&lt;p&gt;Platform events can be published from different places, such as:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Flow&lt;/li&gt;
&lt;li&gt;Process Builder&lt;/li&gt;
&lt;li&gt;Apex&lt;/li&gt;
&lt;li&gt;External apps using API&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Today we are going to consider the third option - publishing a platform event from Apex.&lt;br&gt;
As we need to publish an event when the contact record has been updated with the new Title or Department, let’s create an Apex trigger on the Contact object. Below is the code of this trigger with the comments.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="n"&gt;trigger&lt;/span&gt; &lt;span class="nc"&gt;ContactTrigger&lt;/span&gt; &lt;span class="n"&gt;on&lt;/span&gt; &lt;span class="nf"&gt;Contact&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;before&lt;/span&gt; &lt;span class="n"&gt;update&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Create a static set to store the Contact Ids that have been modified&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="nc"&gt;Set&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Id&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;contactIds&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Set&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Id&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;();&lt;/span&gt;
    &lt;span class="c1"&gt;// Create a list to store the platform events&lt;/span&gt;
    &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;ContactJobChange__e&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;events&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;ContactJobChange__e&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;();&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Trigger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;isBefore&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nc"&gt;Trigger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;isUpdate&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Iterate through the list of updated contacts&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Contact&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Trigger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;new&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// Check if the Contact Id is already in the set&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(!&lt;/span&gt;&lt;span class="n"&gt;contactIds&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;contains&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Id&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                &lt;span class="c1"&gt;// Check if the Title or Department fields have been modified&lt;/span&gt;
                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Title&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="nc"&gt;Trigger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;oldMap&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Id&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;Title&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt;
                    &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Department&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="nc"&gt;Trigger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;oldMap&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Id&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;Department&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                    &lt;span class="c1"&gt;// Add the Contact Id to the set&lt;/span&gt;
                    &lt;span class="n"&gt;contactIds&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;add&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Id&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
                    &lt;span class="c1"&gt;// Create a new platform event&lt;/span&gt;
                    &lt;span class="n"&gt;ContactJobChange__e&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;ContactJobChange__e&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
                    &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ContactId__c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Id&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
                    &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ContactCompany__c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;AccountId&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
                    &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ContactName__c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;FirstName&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="sc"&gt;' '&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;LastName&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
                    &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Department__c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Department&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
                    &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;JobTitle__c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Title&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
                    &lt;span class="c1"&gt;// Add the platform event to the list&lt;/span&gt;
                    &lt;span class="n"&gt;events&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;add&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
                &lt;span class="o"&gt;}&lt;/span&gt;
            &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="nc"&gt;EventBus&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;publish&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;events&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Please note: according to the best practices, it is preferable to keep trigger logic in the separate handler class. This example is simplified for understanding and contains the business logic inside the trigger.&lt;/p&gt;

&lt;h2&gt;
  
  
  Subscribing to the platform event using Workbench
&lt;/h2&gt;

&lt;p&gt;When the trigger logic is done, we can proceed to the subscription to the platform event.&lt;br&gt;
To do this, go to &lt;a href="https://workbench.developerforce.com/" rel="noopener noreferrer"&gt;Workbench&lt;/a&gt; and log in using Salesforce.&lt;br&gt;
Navigate to queries -&amp;gt; Streaming Push Topics. Then select the "Generic Subscriptions" tab and in the "Subscription" field enter the name of your platform event in the following format:&lt;br&gt;
&lt;code&gt;/event/EventName__e&lt;/code&gt;. If you are using an event with a namespace, the format will be the following: &lt;code&gt;/Namespace__event/EventName__e&lt;/code&gt;.&lt;br&gt;
For the ContactJobChange event, I have the following value: &lt;code&gt;/event/ContactJobChange__e&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgwzir9lbym32d0fvkuq2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgwzir9lbym32d0fvkuq2.png" alt="Streaming Push Topics in Workbench menu" width="800" height="196"&gt;&lt;/a&gt;&lt;br&gt;
If everything is set correctly, after filling in all the fields and pressing the "Subscribe" button, you will receive the message that confirms a successful subscription:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F69wk6lg2og54tkabr87x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F69wk6lg2og54tkabr87x.png" alt="Subscribed to event" width="800" height="612"&gt;&lt;/a&gt;&lt;br&gt;
Everything is ready to see how our events work!&lt;/p&gt;

&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;p&gt;Below is a detailed demonstration of how our contact has been updated and event message was received in a real-time:&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh7q2vtjlkzjisi271xvg.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh7q2vtjlkzjisi271xvg.gif" alt="platform event subscription demonstration" width="760" height="399"&gt;&lt;/a&gt;&lt;br&gt;
You may take a look at the received message with the updated JobTitle__c on the following screenshot:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpe3zvf2k4q1uj6cs26qb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpe3zvf2k4q1uj6cs26qb.png" alt="Message received" width="800" height="481"&gt;&lt;/a&gt;&lt;br&gt;
All fields are also filled as expected.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;In this article, we discussed the concept of platform events in Salesforce and how they can be used to track changes in business processes. We also covered how to subscribe to platform events using the Salesforce Workbench tool. We provided step-by-step instructions on how to create a platform event, subscribe to it, and view its data in Workbench. By following these steps, you can easily subscribe to platform events in Workbench, taking full advantage of the real-time data processing capabilities of Salesforce. &lt;/p&gt;

&lt;h2&gt;
  
  
  Lets connect!
&lt;/h2&gt;

&lt;p&gt;If you found this article informative and useful, I would love to connect with you on &lt;a href="https://www.linkedin.com/in/tdrnk/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;. I am always happy to expand my network and connect with individuals who share a passion for Salesforce. Feel free to reach out to me with any questions or feedback regarding the article, I am more than happy to engage in a conversation and provide further assistance. So don't hesitate to connect with me and let's learn and grow together in the Salesforce community!&lt;/p&gt;

</description>
    </item>
    <item>
      <title>LWC getRecords wire adapter: how to retrieve records dynamically</title>
      <dc:creator>Oleksandra Todorenko</dc:creator>
      <pubDate>Fri, 02 Dec 2022 11:34:18 +0000</pubDate>
      <link>https://dev.to/tdrnk/lwc-getrecords-wire-adapter-how-to-retrieve-records-dynamically-apd</link>
      <guid>https://dev.to/tdrnk/lwc-getrecords-wire-adapter-how-to-retrieve-records-dynamically-apd</guid>
      <description>&lt;p&gt;In this article, I would like to share use cases, syntax, workarounds and features of using the &lt;code&gt;getRecords&lt;/code&gt; wire adapter in the Lightning Web Components (LWC) framework in Salesforce.&lt;/p&gt;

&lt;h2&gt;
  
  
  Ways to retrieve record data in LWC
&lt;/h2&gt;

&lt;p&gt;Development by using the LWC often includes some kind of operations with records in the database: creating, retrieving, updating, and deleting.&lt;/p&gt;

&lt;p&gt;There are different ways to retrieve information about the record by its Id while working with LWC. &lt;br&gt;
The simplest and the most limited is by using Lightning Base Components such as “lightning-record-form” or “lightning-record-view-form”. You can retrieve field labels and values for the specific record id and that’s it. The most customizable way is, as always, calling custom Apex. You can retrieve all the needed record details. However, every call to the backend takes more time than operations on the client-side and Apex methods should be called imperatively.&lt;br&gt;
In case you have ids of records (even of different objects!) and want to retrieve their field values (translated and original ones), record type, or last modified details, I recommend using the @wire &lt;code&gt;getRecord&lt;/code&gt; or &lt;code&gt;getRecords&lt;/code&gt; adapter.&lt;/p&gt;
&lt;h2&gt;
  
  
  &lt;code&gt;getRecord&lt;/code&gt; vs &lt;code&gt;getRecords&lt;/code&gt; comparison
&lt;/h2&gt;

&lt;p&gt;These two wire adapters are very similar - both of them belong to 'lightning/uiRecordApi', and accept record id(s) and fields to retrieve parameters.&lt;br&gt;
The only thing is that &lt;code&gt;getRecords&lt;/code&gt; operates over an array of record ids instead of only one id. For sure, it can accept an array that contains only one id.&lt;br&gt;
Also, &lt;code&gt;getRecords&lt;/code&gt; returns a collection of batch result records - each record for each provided id.&lt;br&gt;
If you are unaware of how many record ids should be processed or if you expect more than one id, consider using the &lt;code&gt;getRecords&lt;/code&gt; adapter.&lt;/p&gt;
&lt;h2&gt;
  
  
  Syntax
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;LightningElement&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;wire&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;lwc&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;getRecords&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;lightning/uiRecordApi&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;wire&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;getRecords&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;records&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;recordIds&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt; &lt;span class="na"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="nx"&gt;propertyOrFunction&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;wire&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;getRecords&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;records&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;recordIds&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt; &lt;span class="na"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt; &lt;span class="nx"&gt;optionalFields&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="nx"&gt;propertyOrFunction&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;More details you may find &lt;a href="https://developer.salesforce.com/docs/component-library/documentation/en/lwc/lwc.reference_wire_adapters_records" rel="noopener noreferrer"&gt;in the official documentation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Please note: usage of &lt;code&gt;fields&lt;/code&gt; or &lt;code&gt;optionalFields&lt;/code&gt; parameter is mandatory. The difference is that while using &lt;code&gt;fields&lt;/code&gt; and the context user doesn’t have access to this field, an error occurs. If the user hasn’t access to the field from the &lt;code&gt;optionalFields&lt;/code&gt; parameter - it doesn’t cause an error, just this field won’t be returned. Think about which approach is more convenient in your case and don’t forget that you can use both parameters at the same time.&lt;/p&gt;
&lt;h2&gt;
  
  
  How to retrieve records for dynamic record Ids
&lt;/h2&gt;

&lt;p&gt;There are various examples of retrieving record data using &lt;code&gt;getRecords&lt;/code&gt; for predefined ids for one or for several different objects. Please take a look at the examples from the Salesforce documentation.&lt;/p&gt;

&lt;p&gt;For one object:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;LightningElement&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;wire&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;lwc&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;getRecords&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;lightning/uiRecordApi&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;NAME_FIELD&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@salesforce/schema/User.Name&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;EMAIL_FIELD&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@salesforce/schema/User.Email&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;GetRecordsExample&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;LightningElement&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;wire&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;getRecords&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;records&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
              &lt;span class="na"&gt;recordIds&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;005XXXXXXXXXXXXXXX&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;005XXXXXXXXXXXXXXX&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
              &lt;span class="na"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;NAME_FIELD&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
              &lt;span class="na"&gt;optionalFields&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;EMAIL_FIELD&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="nx"&gt;wiredRecords&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For multiple objects:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;LightningElement&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;wire&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;lwc&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;getRecords&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;lightning/uiRecordApi&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;USER_NAME_FIELD&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@salesforce/schema/User.Name&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;USER_EMAIL_FIELD&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@salesforce/schema/User.Email&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;ACCOUNT_NAME_FIELD&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@salesforce/schema/Account.Name&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;GetRecordsExample&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;LightningElement&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;wire&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;getRecords&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;records&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
              &lt;span class="na"&gt;recordIds&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;005XXXXXXXXXXXXXXX&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
              &lt;span class="na"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;USER_NAME_FIELD&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
              &lt;span class="na"&gt;optionalFields&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;USER_EMAIL_FIELD&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
            &lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
              &lt;span class="na"&gt;recordIds&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;001XXXXXXXXXXXXXXX&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
              &lt;span class="na"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;ACCOUNT_NAME_FIELD&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
            &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="nx"&gt;wiredRecords&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As for now, the main difficulty is the inability (almost) to retrieve records when there are no predefined ids and objects. They are set only statically and there’s no way to write them down dynamically in the array of objects.&lt;/p&gt;

&lt;p&gt;In such an unusual case I recommend creating an array &lt;code&gt;parameterObject&lt;/code&gt; that will include all record parameters as a single property.&lt;br&gt;
This object can be created in the scope of &lt;code&gt;connectedCallback&lt;/code&gt;, &lt;code&gt;renderedCallback&lt;/code&gt;, or at the level of the parent component that calls the current one.&lt;br&gt;
The format will look something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;recordIds&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;recordId&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;parameterObject&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
       &lt;span class="na"&gt;recordIds&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;recordId&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
       &lt;span class="na"&gt;optionalFields&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fieldsToRetrieve&lt;/span&gt;
   &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is the structure that will retrieve records dynamically for different objects when there’s no prepared structure of &lt;code&gt;parameterObject&lt;/code&gt; with predefined Ids. Let’s consider an example of using the &lt;code&gt;getRecords&lt;/code&gt; adapter when records should be retrieved dynamically.&lt;/p&gt;

&lt;h2&gt;
  
  
  Example of using &lt;code&gt;getRecords&lt;/code&gt; for dynamic retrieving data for different objects
&lt;/h2&gt;

&lt;p&gt;Let’s imagine a case when we need to retrieve contact records and the current user’s record and display them in the lightning datatable on Account’s record page.&lt;br&gt;
As &lt;code&gt;getRecords&lt;/code&gt; operates over record Ids, let’s create two components: &lt;code&gt;parentComponent&lt;/code&gt; and &lt;code&gt;childComponent&lt;/code&gt;. Method &lt;code&gt;getContacts&lt;/code&gt; on the parent component will retrieve the Ids of contacts related to the current Account. &lt;strong&gt;Yes, we could retrieve all the record details at this stage from Apex, but we have this logic just to demonstrate a case when we have only Id and no other record data.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;parentComponent.html. Here we transfer &lt;code&gt;contactIds&lt;/code&gt; to the child component.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;template&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;c-child-component&lt;/span&gt; &lt;span class="na"&gt;record-ids=&lt;/span&gt;&lt;span class="s"&gt;{contactIds}&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/c-child-component&amp;gt;&lt;/span&gt; 
&lt;span class="nt"&gt;&amp;lt;/template&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;parentComponent.js&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;LightningElement&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;wire&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;api&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;lwc&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;getContacts&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@salesforce/apex/ContactController.getContactsByAccount&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ParentComponent&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;LightningElement&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;api&lt;/span&gt; &lt;span class="nx"&gt;recordId&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;//current Account's Id&lt;/span&gt;
    &lt;span class="nx"&gt;contactIds&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;

    &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;wire&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;getContacts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;accountId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;$recordId&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="nf"&gt;retrievedContacts&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;}){&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
            &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;contactIds&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
            &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;error: &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And Apex controller ContactController that retrieves contact Ids:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="n"&gt;with&lt;/span&gt; &lt;span class="n"&gt;sharing&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ContactController&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;@AuraEnabled&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cacheable&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Contact&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;getContactsByAccount&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Id&lt;/span&gt; &lt;span class="n"&gt;accountId&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;
                &lt;span class="no"&gt;SELECT&lt;/span&gt;
                    &lt;span class="nc"&gt;Id&lt;/span&gt;
                &lt;span class="no"&gt;FROM&lt;/span&gt;
                    &lt;span class="nc"&gt;Contact&lt;/span&gt;
                &lt;span class="no"&gt;WHERE&lt;/span&gt;
                    &lt;span class="nc"&gt;AccountId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;accountId&lt;/span&gt;
        &lt;span class="o"&gt;];&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The next one is childComponent.html. Here we display all the data in the form of a lightning-datatable Lightning Base Component.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;template&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;template&lt;/span&gt; &lt;span class="na"&gt;if:true=&lt;/span&gt;&lt;span class="s"&gt;{dataIsRetrieved}&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;lightning-datatable&lt;/span&gt;
                &lt;span class="na"&gt;data=&lt;/span&gt;&lt;span class="s"&gt;{dataToDisplay}&lt;/span&gt;
                &lt;span class="na"&gt;columns=&lt;/span&gt;&lt;span class="s"&gt;{columnsToDisplay}&lt;/span&gt;
                &lt;span class="na"&gt;key-field=&lt;/span&gt;&lt;span class="s"&gt;"id"&lt;/span&gt;
                &lt;span class="na"&gt;hide-checkbox-column=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/lightning-datatable&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/template&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/template&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And the last but not least part - childComponent.js.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;LightningElement&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;wire&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;api&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;track&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;lwc&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;getRecords&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;lightning/uiRecordApi&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;CONTACT_NAME_FIELD&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@salesforce/schema/Contact.Name&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;CONTACT_EMAIL_FIELD&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@salesforce/schema/Contact.Email&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;CONTACT_PHONE_FIELD&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@salesforce/schema/Contact.Phone&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;USER_NAME_FIELD&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@salesforce/schema/User.Name&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;USER_EMAIL_FIELD&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@salesforce/schema/User.Email&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;USER_PHONE_FIELD&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@salesforce/schema/User.Phone&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;userId&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@salesforce/user/Id&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ChildComponent&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;LightningElement&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="nx"&gt;dataIsRetrieved&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;contactIds&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;
    &lt;span class="nx"&gt;parameterObject&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;dataToDisplay&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;
    &lt;span class="nx"&gt;columnsToDisplay&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Object&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;fieldName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;object&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Id&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;fieldName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;id&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Name&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;fieldName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Email&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;fieldName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;email&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;email&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Phone&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;fieldName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;phone&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;phone&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Last Modified Date&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;fieldName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;lastModified&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;date&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;];&lt;/span&gt;

    &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;api&lt;/span&gt; &lt;span class="kd"&gt;get&lt;/span&gt; &lt;span class="nf"&gt;recordIds&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;contactIds&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="kd"&gt;set&lt;/span&gt; &lt;span class="nf"&gt;recordIds&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;contacts&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;contactIds&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;contacts&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;parameterObject&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;contactIds&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
            &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;contactIds&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;contact&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;parameterObject&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
                    &lt;span class="na"&gt;recordIds&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;contact&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Id&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
                    &lt;span class="na"&gt;optionalFields&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;CONTACT_NAME_FIELD&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;CONTACT_EMAIL_FIELD&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;CONTACT_PHONE_FIELD&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
                &lt;span class="p"&gt;});&lt;/span&gt;
            &lt;span class="p"&gt;});&lt;/span&gt;
            &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;parameterObject&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
                &lt;span class="na"&gt;recordIds&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
                &lt;span class="na"&gt;optionalFields&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;USER_NAME_FIELD&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nx"&gt;USER_EMAIL_FIELD&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;USER_PHONE_FIELD&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
            &lt;span class="p"&gt;});&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;wire&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;getRecords&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;records&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;$parameterObject&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="nf"&gt;wiredRecords&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;error: &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dataIsRetrieved&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;getRecords results: &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;results&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;results&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;record&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dataToDisplay&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
                    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;record&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;record&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Email&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;record&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="na"&gt;phone&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;record&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Phone&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="na"&gt;object&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;record&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;apiName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="na"&gt;lastModified&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;record&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;lastModifiedDate&lt;/span&gt;
                &lt;span class="p"&gt;});&lt;/span&gt;
            &lt;span class="p"&gt;});&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you may see, &lt;code&gt;getRecords&lt;/code&gt; uses &lt;code&gt;‘$parameterObject’&lt;/code&gt; with all the parameters inside for retrieving records. A dollar sign $ means using a dynamic variable. The method will be called every time when the dynamic variable is updated. However, dynamic update works for &lt;code&gt;getRecord&lt;/code&gt; and other methods that accept primitive types as a parameter, not a collection. That is why I recommend using &lt;code&gt;parameterObject&lt;/code&gt; for &lt;code&gt;getRecords&lt;/code&gt;. This &lt;code&gt;parameterObject&lt;/code&gt; is an array that is filled dynamically when ids of contacts are received from the parentComponent. If the number of Ids or retrieved objects may vary, this is the best workaround for dynamic retrieval records using &lt;code&gt;getRecords&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The final result is the following:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Favc0nps4njyk0lkpk977.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Favc0nps4njyk0lkpk977.png" alt="getRecords result" width="800" height="338"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;To sum up, getRecords is a very useful solution for some specific cases when record data should be retrieved by Id, especially from different objects - to minimize the amount of SOQL queries and calls to the backend.&lt;/p&gt;

&lt;p&gt;If you found this article helpful, I invite you to connect with me on &lt;a href="https://www.linkedin.com/in/tdrnk/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;. I am always looking to expand my network and connect with like-minded individuals in the Salesforce area. Additionally, you can also reach out to me for any questions or feedback on the article. I'd be more than happy to engage in a conversation and help out in any way I can. So don’t hesitate to contact me, and let’s connect and learn together!&lt;/p&gt;

</description>
      <category>emptystring</category>
    </item>
  </channel>
</rss>
