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
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

The software you build is only as secure as the code that powers it. Learn how malicious code creeps into your software supply chain.

Apache Cassandra combines the benefits of major NoSQL databases to support data management needs not covered by traditional RDBMS vendors.

Generative AI has transformed nearly every industry. How can you leverage GenAI to improve your productivity and efficiency?

Modernize your data layer. Learn how to design cloud-native database architectures to meet the evolving demands of AI and GenAI workloads.

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

  • Endpoint Security Controls: Designing a Secure Endpoint Architecture, Part 1
  • Kullback–Leibler Divergence: Theory, Applications, and Implications
  • Simplifying Multi-LLM Integration With KubeMQ
  • Optimizing Integration Workflows With Spark Structured Streaming and Cloud Services
  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
3.6K 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
Oops! Something Went Wrong

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

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

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 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!