top of page
Writer's pictureS. Yadav

DYNAMIC FIELD MAPPING ON BUTTON CLICK USING LWC

Updated: Oct 17, 2023



Dynamic Field Mapping is a powerful capability within Salesforce that provides developers with the flexibility to map and manipulate fields at runtime. This means you can create solutions that adapt to changing field requirements without the need for extensive code modifications. It is particularly useful when you want to allow users to select fields dynamically or when dealing with custom objects where field names may change over time.


As a developer, you may have faced the challenge of mapping the field and value while dynamically creating a record. If the field name for a source or target changes, you can configure a mapping to dynamically get metadata changes at runtime.I will be using an LWC component to create a button that would map source and target together. Before we move forward, please create a new field in Account named ContactEmail. In this blog, I will map Contact’s Email field to Account’s ContactEmail custom field.


Setting Up Custom Metadata Type


1. Create the Custom Metadata Type Create the Custom MetaData type to store field Mapping


2. Define fields in the custom metadata type Source Field - The "SourceField__c" field is designed to specify the source of the data that you want to map. It represents the field from which you intend to extract information. Target Field - The "TargetField__c" field is its counterpart. It defines where the data from the source field should be mapped or deposited. Essentially, it's the field in the destination object where you want to place the data.


3. Adding Records Adding Records to Custom Metadata Type for Dynamic Field Mapping Once you've defined your custom metadata type with fields like "SourceField__c" and "TargetField__c" to facilitate dynamic field mapping in Salesforce, the next crucial step is to populate it with records. These records will define the specific field mappings between the source and target fields in your Salesforce objects. Let's dive into how you can add records to the custom metadata type with a practical example.

Step 1: Navigate to Custom Metadata Types

1. Log in to your Salesforce org. 2. Click on "Setting Gear Icon" in the top-right corner and then Setup. 3. In the search box, type "Custom Metadata Types" and select it.


Step 2: Select Your Custom Metadata Type

On the Custom Metadata Types setup page, you'll see a list of custom metadata types. Click on the custom metadata type you created for your field mappings, which could be named "FieldMapping__mdt" or something similar.


Step 3: Manage Records

On the custom metadata type detail page, you'll find a button labeled "Manage Records" Click on it.


Step 4: Create a New Record

In the "Manage Field Mapping Records" page, click the "New" button to create a new record.


Step 5: Define Field Mappings

You'll see fields corresponding to the fields you defined in your custom metadata type, such as "SourceField__c" and "TargetField__c"

In our example, where we want to map the "Email" field from a source object (Contact) to the "ContactsEmail__c" field in a target object (Account), fill in the fields as follows:

- SourceField__c: Email - TargetField__c: ContactsEmail__c


Step 6: Save the Record After filling in the field values, click the "Save" button to save the record


Code Implementation

1. Create A LWC Component - dynamicFieldMappingButton.html File

<template>
    <lightning-card title="Field Mapping">
        <div class="slds-m-around_medium">
            <lightning-button label="Map Fields"   onclick={handleButtonClick} variant="brand"></lightning-button>
        </div>
    </lightning-card>
</template>

dynamicFieldMappingButton.js File

import { LightningElement, api } from 'lwc';
import {   ShowToastEvent } from 'lightning/platformShowToastEvent';
import   mapFields from '@salesforce/apex/DynamicFieldMappingController.mappedRecord';

export default class DynamicFieldMappingButton extends LightningElement {
    @api recordId;
    handleButtonClick() {
        mapFields({ contactId: this.recordId })
            .then(result => {
                if   (result.isSuccess) {
                    const event = new   ShowToastEvent({
                        title: 'Success',
                        message:   result.message,
                        variant: 'success',
                    });
                    this.dispatchEvent(event);
                } else {
                    const event = new   ShowToastEvent({
                        title: 'Error',
                        message:   result.message,
                        variant: 'error',
                    });
                    this.dispatchEvent(event);
                }
            })
            .catch(error => {
                console.error('Error: ', error);
                const event = new   ShowToastEvent({
                    title: 'Error',
                    message: 'An error occurred while mapping fields.',
                    variant: 'error',
                });
                this.dispatchEvent(event);
            });
    }
   }

dynamicFieldMappingButton.xml File

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

2. Creating the Apex Class:

Introduce the "DynamicFieldMappingControllar" Apex class, which will perform the dynamic field mapping.

public class DynamicFieldMappingController {
    @AuraEnabled
    public static List<DynamicFieldMappingWrapper> mappedRecord(Id contactId)   {
      return new   DynamicFieldMappingProcessor().mapContactToAccount(contactId);
    }
   }

public   List<DynamicFieldMappingWrapper>   mapContactToAccount(Id contactId) {
        List<DynamicFieldMappingWrapper> resultWrapper = new List<DynamicFieldMappingWrapper>();
        List<Contact> contactRecords = new List<Contact>();
        Map<String, String> fieldMappingMap = new Map<String, String>();
        for (FieldMapping__mdt mapping :   DynamicFieldMappingDomain.mapContactToAccount()) {
            if (mapping.TargetField__c != null && mapping.SourceField__c != null) {
                contactRecords =   DynamicFieldMappingDomain.dynamicQuery(mapping, contactId);
                fieldMappingMap.put(mapping.TargetField__c,   mapping.SourceField__c);
            }
        }
        try {
            if (!contactRecords.isEmpty()) {
            Account accountRecord = new Account(
                Name = contactRecords[0].FirstName + ' ' +   contactRecords[0].LastName   +
                ' MappedAccount'
            );
            //   Map and copy data from Contact to Account dynamically using the map
            for (String targetField : fieldMappingMap.keySet()) {
                 accountRecord.put(targetField,
                contactRecords[0].get(fieldMappingMap.get(targetField)
                ));
            }
                insert accountRecord;
                String message = 'Mapping and insertion successful';
                resultWrapper.add(new   DynamicFieldMappingWrapper(true, message));
               
            }
        }
        catch (Exception ex) {
            String message = 'Mapping   failed due to an error: ' + ex.getMessage();
            resultWrapper.add(new   DynamicFieldMappingWrapper(false, message));
        }
        return resultWrapper;
    }
   }

public with sharing class DynamicFieldMappingWrapper {
    @AuraEnabled
    public Boolean isSuccess { get; set; }
    @AuraEnabled
    public String message { get; set; }
    public DynamicFieldMappingWrapper() {
        this.isSuccess = false;
        this.message = '';
    }
    public DynamicFieldMappingWrapper(Boolean isSuccess, String message) {
        this.isSuccess = isSuccess;
        this.message = message;
    }
   }
public class DynamicFieldMappingDomain {
    public static List<FieldMapping__mdt> mapContactToAccount(Id   contactId) {
        //   Query the field mapping records from custom metadata
        List<FieldMapping__mdt> fieldMappings = [
            SELECT
                SourceField__c,
                TargetField__c
            FROM
                FieldMapping__mdt
        ];
        return fieldMappings;
    }

    public static List<Contact> dynamicQuery(FieldMapping__mdt mappings,   Id contactId) {
        String dynamicQuery = 'SELECT Id, FirstName, LastName, ' + mappings.SourceField__c +
            '   FROM Contact WHERE Id = :contactId LIMIT 1';
        List<Contact> contactRecords =   Database.query(dynamicQuery);
        return contactRecords;
    }
   }

Testing Mapped Data

  • New contact record

    1. You can create a new contact record from the UI and use the new contact record ID for further code execution.

    2. The new contact should have an email. (This email will be reflected in the related Account ContactEmail field.

    3. Now go to Contact Details.

  • Add LWC component to Contact record page

Click on the edit page from the new contact, drag and drop the custom LWC component “dynamicFieldMappingButton” as needed, and save.


  • Map data with LWC Button

Click on Map Fields Button


When you click the button you get Success Message.


  • Open Accounts

You will see a new account created as a combination of the Contact name and mapped account. Verify the ContactEmail field with the email entered in the previously created contact record.



Conclusion

In conclusion, dynamic field mapping in Salesforce using custom metadata types is a powerful technique for handling changing field requirements. By separating field mappings from code, developers can ensure their applications remain adaptable to evolving data structures. With practical examples and a solid understanding of the process, you can confidently implement dynamic field mapping in your Salesforce projects.


If you'd like to see the code and resources used in this project, you can access the repository on GitHub.To access the AVENOIRBLOGS repository, click here. Feel free to explore the code and use it as a reference for your own projects.


Happy Coding! You can leave a comment to help me understand how the blog helped you. If you need further assistance, please contact us. You can click "Reach Us" on the website and share the issue with me.



Blog Credit:

S. Yadav

Salesforce Developer

Avenoir Technologies Pvt. Ltd.


Reach us: team@avenoir.ai

1 Comment


Swapnil Dewangan
Swapnil Dewangan
Oct 26, 2023

Great content

Like
bottom of page