DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Related

  • Top Tools for Object Storage and Data Management
  • How To Use IBM App Connect To Build Flows
  • Prototype Pattern in JavaScript
  • Building an AWS Integration for Salesforce Image Handling

Trending

  • The ORM Is Over: AI-Written SQL Is the New Data Access Layer
  • Docker Hardened Images Are Free Now — Here's What You Still Need to Build
  • Why SAP S/4HANA Landscape Design Impacts Cloud TCO More Than Compute Costs
  • Building Production-Grade GenAI on GCP with Vertex AI Agent Builder
  1. DZone
  2. Coding
  3. Tools
  4. Dynamic File Upload Component in Salesforce LWC

Dynamic File Upload Component in Salesforce LWC

Build an LWC allowing users to dynamically configure the object and fields they want to upload data to, download a template for these fields, and more.

By 
Balusamy Nachiappan user avatar
Balusamy Nachiappan
·
Oct. 07, 24 · Code Snippet
Likes (2)
Comment
Save
Tweet
Share
5.8K Views

Join the DZone community and get the full member experience.

Join For Free

In Salesforce, the ability to import and export data dynamically is crucial for many business processes. While standard Salesforce tools provide basic import/export functionality, custom solutions can offer enhanced flexibility and user experience. In this blog, we will build a Lightning Web Component (LWC) that allows users to dynamically configure the object and fields they want to upload data to, download a template for these fields, and then upload data. Furthermore, we’ll display error and success messages in a popup modal to improve user interaction.

By the end of this tutorial, you will have a reusable component that simplifies data imports and guides users through the process with clear feedback.

1. Setting Up the LWC Component

Our component will include:

  1. Object and field configuration from Meta XML: The object name and fields will be configured using properties defined in the LWC’s js-meta.xml file.
  2. Downloadable template: The component will generate a downloadable template based on the configured fields.
  3. File upload capability: Users can upload a CSV or Excel file that matches the template format.
  4. Modal popups for feedback: Display error or success messages in a popup modal for a better user experience.

LWC Meta XML Configuration (dynamicUploadComponent.js-meta.xml)

We define the object name and fields as configurable properties in the meta XML file. These properties will be set when adding the component to a Lightning page.

XML
 
<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>57.0</apiVersion>
    <isExposed>true</isExposed>
    <targets>
        <target>lightning__RecordPage</target>
        <target>lightning__AppPage</target>
        <target>lightning__HomePage</target>
    </targets>
    <targetConfigs>
        <targetConfig targets="lightning__RecordPage,lightning__AppPage,lightning__HomePage">
            <property name="objectName" type="String" label="Object Name" description="API Name of the Salesforce Object"/>
            <property name="fieldNames" type="String" label="Field Names" description="Comma separated API Names of the fields"/>
        </targetConfig>
    </targetConfigs>
</LightningComponentBundle>


LWC HTML Template (dynamicUploadComponent.html)

The HTML template includes a section for displaying object and field information, buttons to download the template, and upload file input. It also includes a modal popup to display messages.

XML
 
<template>
<lightning-card title="Dynamic File Upload">
<!-- Display configured object name and fields -->
<p class="slds-m-around_medium">Object: {objectName}
</p>
<p class="slds-m-around_medium">Fields: {fieldNames}
</p>
<!-- Download Template Button -->
<lightning-button label="Download Template" onclick={downloadTemplate} class="slds-m-around_medium" disabled={disableTemplateDownload}>
</lightning-button>
<!-- File Upload -->
  <lightning-file-upload            label="Upload File"            accept=".csv,.xlsx"            record-id={recordId}            onuploadfinished={handleUploadFinished}            multiple={false}            class="slds-m-around_medium">
  </lightning-file-upload>
  <!-- Modal Popup for Error and Success Messages -->
    <template if:true={showModal}>
      <section role="dialog" tabindex="-1" class="slds-modal slds-fade-in-open">
        <div class="slds-modal__container">
          <header class="slds-modal__header">
            <button class="slds-button slds-button_icon slds-modal__close slds-button_icon-inverse" title="Close" onclick={closeModal}>
              <lightning-icon icon-name="utility:close" alternative-text="close" size="small">
              </lightning-icon>
              <span class="slds-assistive-text">Close
              </span>
            </button>
            <h2 class="slds-text-heading_medium">{modalTitle}
            </h2>
          </header>
          <div class="slds-modal__content slds-p-around_medium">
            <p>{modalMessage}
            </p>
          </div>
          <footer class="slds-modal__footer">
            <lightning-button variant="neutral" label="Close" onclick={closeModal}>
            </lightning-button>
          </footer>
        </div>
      </section>
      <div class="slds-backdrop slds-backdrop_open">
      </div>
    </template>
  </lightning-card>
</template>


LWC JavaScript Controller (dynamicUploadComponent.js)

This script handles the logic for downloading templates, processing uploaded files, and displaying feedback in a modal popup.

JavaScript
 
import { LightningElement, track, api } from 'lwc';
import { saveAs } from 'file-saver';
import * as XLSX from 'xlsx';
import getObjectFields from '@salesforce/apex/DynamicUploadController.getObjectFields';
import insertRecords from '@salesforce/apex/DynamicUploadController.insertRecords';
export default class DynamicUploadComponent extends LightningElement {
    @api objectName; // Object name from meta XML
    @api fieldNames; // Field names from meta XML
    @track disableTemplateDownload = false; // Enable template download initially
    @track showModal = false; // Control the display of the modal
    @track modalTitle = ''; // Modal title
    @track modalMessage = ''; // Modal message
    connectedCallback() {
        // Check if objectName and fieldNames are provided
        if (!this.objectName || !this.fieldNames) {
            this.disableTemplateDownload = true;
            this.showModalMessage('Error', 'Object Name and Field Names are required.');
        }
    }


    // Download template based on the object name and field names
    downloadTemplate() {
        this.showModal = false;
        const fieldsArray = this.fieldNames.split(',').map(field => field.trim());
        this.generateTemplate(fieldsArray);
    }

    // Generate CSV/Excel template with field names as header

    generateTemplate(fields) {
        const csvString = fields.join(',') + '\n';
        const blob = new Blob([csvString], { type: 'text/csv;charset=utf-8;' });
        saveAs(blob, `${this.objectName}_Template.csv`);
    }

    // Handle file upload and process the data

   handleUploadFinished(event) {
        this.showModal = false;
        const uploadedFiles = event.detail.files;
        if (uploadedFiles.length > 0) {
            this.processUploadedFile(uploadedFiles[0]);
        }
    }

    // Process uploaded file
    processUploadedFile(file) {
        const reader = new FileReader();
        reader.onload = () => {
            const content = reader.result;
            const workbook = XLSX.read(content, { type: 'binary' });
            const sheetName = workbook.SheetNames[0];
            const sheet = workbook.Sheets[sheetName];
            const csvData = XLSX.utils.sheet_to_json(sheet, { header: 1 });
            if (csvData.length > 1) {
                this.uploadData(csvData);
            } else {
                this.showModalMessage('Error', 'The uploaded file is empty or has no data rows.');
            }
        };
        reader.onerror = () => {
            this.showModalMessage('Error', 'Error reading the uploaded file.');
        };
        reader.readAsBinaryString(file);
    }



    // Upload data to Salesforce
    uploadData(csvData) {
        const fields = csvData[0];
        const records = [];
        for (let i = 1; i < csvData.length; i++) {
            let record = {};
            for (let j = 0; j < fields.length; j++) {
                record[fields[j]] = csvData[i][j] || '';
            }
            records.push(record);
        }

        insertRecords({ objectName: this.objectName, records: JSON.stringify(records) })
            .then(() => {
                this.showModalMessage('Success', 'Records have been successfully uploaded.');
            })
            .catch(error => {
                this.showModalMessage('Error', `Error uploading records: ${error.body.message}`);
            });
    }


    // Show modal with error or success message
    showModalMessage(title, message) {
        this.modalTitle = title;
        this.modalMessage = message;
        this.showModal = true;
    }

    // Close the modal
    closeModal() {
        this.showModal = false;
    }
}


LWC CSS (dynamicUploadComponent.css)

Add styles for the modal popup.

CSS
 
.slds-modal__container {    width: 50%;    max-width: 50rem; }
.slds-modal__header {    display: flex;    justify-content: space-between;    align-items: center; }
.slds-modal__footer {    text-align: right; }


2. Creating the Apex Controller

We use an Apex controller to dynamically retrieve fields for the configured object and to insert records into Salesforce.

Apex Controller (DynamicUploadController.cls)

Java
 
public with sharing class DynamicUploadController {
    @AuraEnabled(cacheable=true)
    public static List<String> getObjectFields(String objectName) {
        // Retrieve field names for the specified object
        try {
            Map<String, Schema.SObjectField> fieldsMap = Schema.getGlobalDescribe().get(objectName).getDescribe().fields.getMap();
            return new List<String>(fieldsMap.keySet());
        } catch (Exception e) {
            throw new AuraHandledException('Error fetching fields: ' + e.getMessage());
        }
    }
    @AuraEnabled
    public static void insertRecords(String objectName, String records) {
        // Insert records into the specified object
        if (String.isBlank(objectName) || String.isBlank(records)) {
            throw new AuraHandledException('Object Name and Records cannot be empty.');
        }
        List<SObject> sObjectList = new List<SObject>();
        List<Map<String, Object>> recordList = (List<Map<String, Object>>) JSON.deserializeUntyped(records);

        for (Map<String, Object> recordMap : recordList) {
            SObject sObjectRecord = (SObject) Schema.getGlobalDescribe().get(objectName).newSObject(null, true);
            for (String fieldName : recordMap.keySet()) {
                sObjectRecord.put(fieldName, recordMap.get(fieldName));
            }
            sObjectList.add(sObjectRecord);
        }

        try {
            insert sObjectList;
        } catch (Exception e) {
            throw new AuraHandledException('Error inserting records: ' + e.getMessage());
        }
    }

}


3. Using the Component

  1. Add the component to a Lightning page: Use the App Builder to place the dynamicUploadComponent on a Lightning record, app, or home page.
  2. Configure the component: Set the objectName and fieldNames properties in the component configuration.
  3. Download the template: Click the "Download Template" button to get the CSV template for the specified object and fields.
  4. Upload data: Fill in the template and upload it using the file upload component. The data will be validated and inserted into Salesforce.

Conclusion

Now you have created a flexible and reusable LWC component for data upload with Salesforce. This component guides users through the process with configurable templates, improving the overall user experience. You can further extend this component by adding features such as:

  • Advanced data validation: Implement checks for required fields and data formats.
  • Customizable modal: Enhance the modal with additional actions or styling options.

This dynamic upload component is a powerful tool for any Salesforce implementation, offering a streamlined solution for data import tasks.

Upload Object (computer science) Record (computer science) Template Sales engineering Tool

Opinions expressed by DZone contributors are their own.

Related

  • Top Tools for Object Storage and Data Management
  • How To Use IBM App Connect To Build Flows
  • Prototype Pattern in JavaScript
  • Building an AWS Integration for Salesforce Image Handling

Partner Resources

×

Comments

The likes didn't load as expected. Please refresh the page and try again.

  • RSS
  • X
  • Facebook

ABOUT US

  • About DZone
  • Support and feedback
  • Community research

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 215
  • Nashville, TN 37211
  • [email protected]

Let's be friends:

  • RSS
  • X
  • Facebook