Create Image Cropper in Salesforce Lightning Web Component : Bijay Kumar

Create Image Cropper in Salesforce Lightning Web Component
by: Bijay Kumar
blow post content copied from  SalesForce FAQs
click here to view original post



### Summary of Creating an Image Cropper in Salesforce Using Lightning Web Component This guide explains how to build an image cropper in Salesforce using Lightning Web Components (LWC) and the Croppie JavaScript library. The component allows users to upload a profile picture, crop it, and save it directly to a Contact record in Salesforce, similar to social media platforms. #### Key Steps: 1. **Setting Up Croppie**: - Download the Croppie library files (`croppie.css` and `croppie.js`) and upload them as static resources in Salesforce. 2. **Creating the Lightning Web Component**: - Use Visual Studio Code to create a new LWC named `imageCropper`, which will consist of three files: `imageCropper.js`, `imageCropper.html`, and `imageCropper-meta.xml`. 3. **Importing the Croppie Library**: - In the JavaScript file, import the Croppie library and load it using `loadScript` and `loadStyle`. 4. **Handling Image Upload and Cropping**: - Implement the `handleFileChange` method to read the uploaded image and initialize the Croppie instance for cropping. 5. **Creating the User Interface**: - Use HTML to create a layout that includes a file input for image uploads and a cropping area. 6. **Saving the Cropped Image**: - Create an Apex controller to handle the image upload to the Salesforce Contact record. - Implement the `handleSave` method in the JavaScript file to save the cropped image as a base64 string. 7. **Deploying the Component**: - Expose the component to Lightning pages and deploy it on the Contact record page. 8. **User Interaction**: - Users can upload an image, crop it, and save it. A success message will appear upon successful upload, and the image will be stored in the `Profile_picture_c` field of the Contact object. ### Additional Context: This feature enhances user experience by allowing easy image uploads and modifications directly within Salesforce, making it more user-friendly and visually appealing. The use of Croppie simplifies the cropping process, providing a familiar interface for users. ### Relevant Hashtags for SEO: #Salesforce #LightningWebComponents #ImageCropper #Croppie #SalesforceDevelopment #LWC #WebDevelopment #Apex #SalesforceCustomization #UserExperience #ProfilePictureUpload #SalesforceTips This summary provides a clear understanding of how to implement an image cropper in Salesforce, along with the necessary steps and context to appreciate its functionality.


Have you ever wanted to let users upload a profile picture in Salesforce with an easy cropping experience? This is similar to what we get when uploading profile pictures on social media apps. There, we see the option to crop the image before uploading.

We can create an image cropper in Salesforce with Lightning Web Component using the external JS library.

Create Image Cropper in Lightning Web Component Using JS Library

In the steps below, we will create the image cropper using the JS library Croppie in the Lightning Web Component, and the cropped image will be saved in the Contact record.

Set Up Croppie as a Static Resource

To use the external JS library, we need to create a static resource that we can import into the Lightning Web Component. Download it first from https://ift.tt/Jj2qd8b. We only need the croppie.css and croppie.js files from the library.

Create an Image Cropper in Salesforce lwc

To create a static resource, navigate to Salesforce setup > static resource. Then, create a static resource with the name croppieCss, upload the croppie.css, and make the cache control Public.

Salesforce LWC image cropper

In the same way, create another static resourcecroppieCSS, and upload the croppie.CSS file.

How to use Image cropper library in JS

After creating the static resource for the JS library, let’s move ahead and create the Lightning Web Component.

Create the Lightning Web Component

To create the Lightning Web Component, navigate to the VS Code IDE that you have set up with the Salesforce org.

In VS Code, press the button ctrl+shift+p and in the command palette select SFDX: Create Lightning Web Component.

Salesforce lightning web component image cropper

Give the name of the component in camel case, such as imageCropper.

As we create the Lightning Web Component, we will have three files in the LWC folder imageCropper that are imageCropper.js, imageCropper.html, and imageCropper-meta.xml.

Import Croppie Library into the Component

To use the JS library in the Lightning Web Component, we must import the croppie library from the static resource we created. Enter the code below in the JS file.

import { LightningElement, api } from 'lwc';
import { loadScript, loadStyle } from 'lightning/platformResourceLoader';
import cropCss from '@salesforce/resourceUrl/croppieCss';
import cropJS from '@salesforce/resourceUrl/croppieJs';

With this, we have imported the library files croppie.js and croppie.css. The {loadScript, loadstyle} are used when we have imported any external CSS and JS files.

To invoke the JS library croppie, enter the below method in the JS file.

renderedCallback() {
        if (this.croppieLoaded) return;

        Promise.all([loadStyle(this, cropCss), loadScript(this, cropJS)])
            .then(() => {
                this.croppieLoaded = true;
            })
            .catch((error) => {
                this.showToast('Error', 'Failed to load Croppie resources', 'error');
                console.error('Croppie load error:', error);
            });
    }

Handle Image File Upload and Cropping Logic

To handle the image file selected by the user and display it inside the cropper, we need to handle file input changes and initialize the Croppie instance with the uploaded image. For this, we’ll write the handleFileChange method as shown below:

handleFileChange(event) {
        const file = event.target.files[0];
        if (!file) return;

        this.fileName = file.name;
        this.fileSizeInMb = (file.size / (1024 * 1024)).toFixed(2);

        const reader = new FileReader();
        reader.onload = () => {
            const cropElement = this.template.querySelector('[data-id="custom"]');
            if (this.fileDetailReader) {
                this.fileDetailReader.destroy();
            }

            this.fileDetailReader = new window.Croppie(cropElement, {
                viewport: { width: 199, height: 199, type: 'circle' },
                boundary: { width: 250, height: 250 },
                showZoomer: true
            });

            this.fileDetailReader.bind({ url: reader.result });
        };
        reader.readAsDataURL(file);
    }

In the above code, we first extracted the uploaded file from the event and stored its name and size. Then we use FileReader to convert the file into a Data URL, which is required by the Croppie library to display the image.

Once the image is read, it selects the container (with data-id=”custom”) and initializes a new Croppie instance with a circular cropping area as shown below.

Crop image using LWC in Salesforce

Create an Image Cropper UI with HTML

To enable users to upload an image and preview it for cropping, we will set up a user interface for the LWC image cropper. The HTML below creates a responsive layout with a file input on one side and the cropping area on the other.

<template>
    <div class="slds-box slds-theme_default slds-p-around_medium">
        <template if:true={croppieLoaded}>
            <div class="slds-grid slds-wrap slds-gutters">
                <div class="slds-col slds-size_1-of-1 slds-medium-size_1-of-2">
                    <div class="slds-m-bottom_medium">
                        <div data-id="custom" class="imge-cropping" style="margin: auto;"></div>
                    </div>
                </div>

                <div class="slds-col slds-size_1-of-1 slds-medium-size_1-of-2">
                    <div class="slds-form-element slds-m-bottom_medium">
                        <div class="slds-file-selector slds-file-selector_files">
                            <div class="slds-file-selector__dropzone">
                                <input type="file" class="slds-file-selector__input slds-assistive-text" accept=".png, .jpg, .jpeg" id="img-crop-input" onchange={handleFileChange} />
                                <label class="slds-file-selector__body" for="img-crop-input">
                                    <span class="slds-file-selector__button slds-button slds-button_neutral">
                                        <lightning-icon icon-name="doctype:image" size="small" alternative-text="Upload Picture" class="slds-m-right_small"></lightning-icon>
                                        Upload Picture
                                    </span>
                                </label>
                            </div>
                        </div>
                    </div>

                    <template if:true={fileName}>
                        <p class="slds-text-title_caps slds-m-bottom_x-small">Filename: {fileName}</p>
                        <p class="slds-text-body_regular">Size: {fileSizeInMb} MB</p>
                    </template>

                </div>
            </div>
        </template>
    </div>
</template>

The file input accepts .png, .jpg, and .jpeg files and triggers handleFileChange on change. After a file is selected, its name and size are displayed below the upload button.

Expose Component to Lightning Pages

Now, make the Lightning Web Component exposed to the Lightning pages using the code below.

<isExposed>true</isExposed>
    <targets>
        <target>lightning__AppPage</target>
        <target>lightning__RecordPage</target>
        <target>lightning__HomePage</target>
    </targets>

Next, navigate to the Lightning page and deploy the Lightning web component.

Lightning web component image cropper

Currently, we have created a lighting web component that allows us to upload and crop images. But the UI is looking very dull, so we will enhance it and add logic to save the cropped image in the object record.

Save Cropped Image to Salesforce Record

We will store the cropped image in the Contact object’s custom rich text field Profile_picture_c.

To handle the logic for saving the cropped image in the contact field, we need to create an Apex controller class as follows.

public with sharing class CroppieCtrl {
    @AuraEnabled
    public static String insertProfilePic(String filename, String filebase, String recordid) {
        ContentVersion cVersion = new ContentVersion();
        cVersion.ContentLocation = 'S';
        cVersion.PathOnClient = filename;
        cVersion.Title = filename;
        cVersion.VersionData = EncodingUtil.base64Decode(filebase);
        cVersion.IsMajorVersion = true;
        insert cVersion;

        ContentVersion conVersion = [SELECT Id, ContentDocumentId FROM ContentVersion WHERE Id = :cVersion.Id LIMIT 1];
        ContentDocumentLink cDocLink = new ContentDocumentLink();
        cDocLink.ContentDocumentId = conVersion.ContentDocumentId;
        cDocLink.LinkedEntityId = recordId;
        cDocLink.Visibility = 'AllUsers';
        insert cDocLink;

        ContentDistribution dist = new ContentDistribution();
        dist.ContentVersionId = conVersion.Id;
        dist.Name = 'PublicLink';
        dist.PreferencesNotifyOnVisit = false;
        insert dist;

        return dist.ContentDownloadUrl;
    }
}

This controller class uploads the image as a ContentVersion, links it to a record using ContentDocumentLink, and returns a public download URL via ContentDistribution.

Now, enter the updated code for the imageCropper.js file, in which we have imported the controller class and also the toast notification feature ShowToastEvent.

import { LightningElement, api } from 'lwc';
import { loadScript, loadStyle } from 'lightning/platformResourceLoader';
import cropCss from '@salesforce/resourceUrl/croppieCss';
import cropJS from '@salesforce/resourceUrl/croppieJs';
import insertProfilePic from '@salesforce/apex/CroppieCtrl.insertProfilePic';
import { ShowToastEvent } from 'lightning/platformShowToastEvent';

export default class ImageCropper extends LightningElement {
    croppieLoaded = false;
    fileDetailReader;
    fileName;
    fileSizeInMb;
    previewUrl;
    fileData;
    @api recordId;

    renderedCallback() {
        if (this.croppieLoaded) return;

        Promise.all([loadStyle(this, cropCss), loadScript(this, cropJS)])
            .then(() => {
                this.croppieLoaded = true;
            })
            .catch((error) => {
                this.showToast('Error', 'Failed to load Croppie resources', 'error');
                console.error('Croppie load error:', error);
            });
    }

    handleFileChange(event) {
        const file = event.target.files[0];
        if (!file) return;

        this.fileName = file.name;
        this.fileSizeInMb = (file.size / (1024 * 1024)).toFixed(2);

        const reader = new FileReader();
        reader.onload = () => {
            const cropElement = this.template.querySelector('[data-id="custom"]');
            if (this.fileDetailReader) {
                this.fileDetailReader.destroy();
            }

            this.fileDetailReader = new window.Croppie(cropElement, {
                viewport: { width: 199, height: 199, type: 'circle' },
                boundary: { width: 250, height: 250 },
                showZoomer: true
            });

            this.fileDetailReader.bind({ url: reader.result });
        };
        reader.readAsDataURL(file);
    }

    handleSave() {
        if (!this.fileDetailReader) {
            this.showToast('Error', 'Please upload and crop an image first', 'warning');
            return;
        }

        this.fileDetailReader.result({ type: 'base64' }).then((result) => {
            this.fileData = result.split(',')[1];
            this.previewUrl = result;

            insertProfilePic({
                filename: this.fileName,
                filebase: this.fileData,
                recordid: this.recordId
            })
                .then((url) => {
                    this.showToast('Success', 'Profile picture uploaded successfully', 'success');
                    this.dispatchEvent(
                        new CustomEvent('photouploaded', {
                            detail: {
                                photoUrl: url,
                                type: 'save',
                                uploaded: true
                            }
                        })
                    );
                })
                .catch((error) => {
                    this.showToast('Error', 'Upload failed', 'error');
                    console.error(error);
                });
        });
    }

    showToast(title, message, variant) {
        this.dispatchEvent(
            new ShowToastEvent({
                title,
                message,
                variant
            })
        );
    }
}

In the above code, we have defined variables previewUrl, fileData, and recordId.

  • previewUrl: It uses Base64 to show the preview of the cropped image.
  • fileData: Base64 content to send to Apex.
  • recordId: This will get the ID of the record page and save the cropped image.

The handleSave() method will save the cropped image in the current record of the Contact object. When the user clicks the Save button, the component checks if an image was cropped. It then uses Croppie’s result method to get the cropped image in base64 format, removes the header, and sends it to the Apex insertProfilePic method for saving.

On success, it shows a success toast message using the ShowToastEvent.

After this, update the imageCropper.html following the code below.

<template>
<lightning-card title="LWC Image Cropper" icon-name="utility:image">
    <div class="slds-box slds-theme_default slds-p-around_medium">
        <template if:true={croppieLoaded}>
            <div class="slds-grid slds-wrap slds-gutters">
               
                <div class="slds-col slds-size_1-of-1 slds-medium-size_1-of-2">
                    <h3 class="slds-text-heading_small slds-m-bottom_small">Crop Image</h3>
                    <div data-id="custom" class="imge-cropping slds-align_absolute-center"></div>
                </div>

                <div class="slds-col slds-size_1-of-1 slds-medium-size_1-of-2">
                    <div class="slds-m-bottom_medium">
                        <label class="slds-form-element__label" for="img-crop-input">Choose Image</label>
                        <div class="slds-file-selector slds-file-selector_files">
                            <div class="slds-file-selector__dropzone">
                                <input type="file" class="slds-file-selector__input slds-assistive-text" accept=".png, .jpg, .jpeg" id="img-crop-input" onchange={handleFileChange} />
                                <label class="slds-file-selector__body" for="img-crop-input">
                                    <span class="slds-file-selector__button slds-button slds-button_neutral">
                                        <lightning-icon icon-name="doctype:image" size="small" class="slds-m-right_small"></lightning-icon>
                                        Upload Picture
                                    </span>
                                </label>
                            </div>
                        </div>
                        <template if:true={fileName}>
                            <p class="slds-m-top_small"><strong>File:</strong> {fileName}</p>
                            <p><strong>Size:</strong> {fileSizeInMb} MB</p>
                        </template>
                    </div>

                    <template if:true={previewUrl}>
                        <h3 class="slds-text-heading_small slds-m-bottom_small">Preview</h3>
                        <img src={previewUrl} alt="Cropped Preview" class="slds-box slds-m-bottom_medium" style="max-width: 200px; border-radius: 50%;" />
                    </template>

                    <lightning-button variant="brand" label="Save Image" onclick={handleSave} class="slds-m-top_medium"></lightning-button>
                </div>
            </div>
        </template>
    </div>
</template>

In the HTML, we have now added the card title as “LWC Image cropper” using the lightning-card-title tag.

To display the image preview after cropping, we have defined handleFileChange(), which reads the cropped image using the FileReader. Now, the cropped image is not yet saved, but is displayed in the preview section by setting the previewUrl property to the cropped image.

In the handleSave(), when the user clicks the save button, the cropped image is converted to base64, the header is removed, and the raw data is sent to the Apex method insertProfilePic along with the file name and Contact record ID.

On successfully saving the records, the toast notification will display a success message.

With this, the LWC image cropper is ready with the modified changes, where we can also preview and save the cropped images.

Deploy the Image Cropper on the Contact Record Page

We are going to deploy the Contact record according to the logic that we have defined. The controller class will convert the uploaded image file into a text string using the Base64 method of encoding binary data, and the image will be stored in the Profile_picture_c field.

Ensure that you have added the target for the record page to the meta.xml file, as shown below.

<targets>
        <target>lightning__RecordPage</target>
    </targets>

Navigate to the Contact tab and open any of the contact records. Then click on the settings icon and select Edit Page.

In the Lightning app builder, add the LWC to the page region and save the changes.

Create a Lightning web component to crop image

After this, navigate back to the record page, and there you will see the LWC image cropper with the updated UI.

Here, click on the Upload Picture button and browse the image, then adjust the image in the circle frame using the slider and dragging the image.

After that, click on the Save button. On successful upload, a toast message will appear on the screen.

Use JS library to Create an LWC image cropper

To view the uploaded image, scroll down to the ‘Notes and Attachments’ section.

Salesforce Lightning Custom Image Cropper

This way, we have also saved the cropped image in the object record.

This is how we can create a fully functional image cropper in Salesforce using the Lightning Web Component and the Croppie JavaScript library. With this component, we can easily upload, crop, and save images directly to Salesforce records.

Just ensure that you upload the Croppie library properly, link it in the static resource, and handle the image data correctly in your Apex method.

You may also like to read:

The post Create Image Cropper in Salesforce Lightning Web Component appeared first on SalesForce FAQs.


April 21, 2025 at 09:36AM
Click here for more details...

=============================
The original post is available in SalesForce FAQs by Bijay Kumar
this post has been published as it is through automation. Automation script brings all the top bloggers post under a single umbrella.
The purpose of this blog, Follow the top Salesforce bloggers and collect all blogs in a single place through automation.
============================

Salesforce