In this blog I will share the code to preview files in a Modal in Lightning Web Component.
There are three component in this example -
1. PreviewFileThumbnails - The parent component to upload the file.
2. PreviewFileThumbnailCard - Child component to display image preview in a thumbnail gallery view.
3. PreviewFileModal - Child component to display selected thumbnail file in a new modal popup for preview.
Make sure to change below PDF setting in Salesforce org to see the preview in browser otherwise it will download the file instead of preview :
Go to Setup --> Security --> File Upload and Download Security
Hit edit and update the .pdf file settings to "Execute in Browser" as shown in the image below :
You may follow the code below now.
PreviewFileThumbnails.html
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | <template> <lightning-file-upload name="fileUploader" accept={acceptedFormats} record-id={recordId} onuploadfinished={handleUploadFinished} multiple > </lightning-file-upload> <br /> <div class=" slds-page-header__row slds-var-m-top_x-small slds-var-m-left_medium slds-grid slds-wrap " > <ul class="slds-grid slds-wrap slds-gutters"> <template if:true={loaded}> <template for:each={files} for:item="file"> <c-preview-file-thumbnail-card key={file.Id} file={file} record-id={recordId} thumbnail={file.thumbnailFileCard} ></c-preview-file-thumbnail-card> </template> </template> </ul> </div> </template> |
PreviewFileThumbnails.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 | import { LightningElement, wire, api, track } from "lwc"; import { refreshApex } from "@salesforce/apex"; import { ShowToastEvent } from "lightning/platformShowToastEvent"; import getFileVersions from "@salesforce/apex/FileController.getVersionFiles"; export default class PreviewFileThumbnails extends LightningElement { loaded = false; @track fileList; @api recordId; @track files = []; get acceptedFormats() { return [".pdf", ".png", ".jpg", ".jpeg"]; } @wire(getFileVersions, { recordId: "$recordId" }) fileResponse(value) { this.wiredActivities = value; const { data, error } = value; this.fileList = ""; this.files = []; if (data) { this.fileList = data; for (let i = 0; i < this.fileList.length; i++) { let file = { Id: this.fileList[i].Id, Title: this.fileList[i].Title, Extension: this.fileList[i].FileExtension, ContentDocumentId: this.fileList[i].ContentDocumentId, ContentDocument: this.fileList[i].ContentDocument, CreatedDate: this.fileList[i].CreatedDate, thumbnailFileCard: "/sfc/servlet.shepherd/version/renditionDownload?rendition=THUMB720BY480&versionId=" + this.fileList[i].Id + "&operationContext=CHATTER&contentId=" + this.fileList[i].ContentDocumentId, downloadUrl: "/sfc/servlet.shepherd/document/download/" + this.fileList[i].ContentDocumentId }; this.files.push(file); } this.loaded = true; } else if (error) { this.dispatchEvent( new ShowToastEvent({ title: "Error loading Files", message: error.body.message, variant: "error" }) ); } } handleUploadFinished(event) { const uploadedFiles = event.detail.files; refreshApex(this.wiredActivities); this.dispatchEvent( new ShowToastEvent({ title: "Success!", message: uploadedFiles.length + " Files Uploaded Successfully.", variant: "success" }) ); } } |
PreviewFileThumbnailCard.html
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 | <template> <template if:true={file}> <c-preview-file-modal url={file.downloadUrl} file-extension={file.Extension} ></c-preview-file-modal> <li class=" slds-col slds-var-p-vertical_x-small slds-small-size_1-of-2 slds-medium-size_1-of-4 slds-large-size_1-of-6 " > <div class="slds-file slds-file_card slds-has-title" style="width: 14rem" onclick={filePreview} > <figure> <a class="slds-file__crop slds-file__crop_4-by-3 slds-m-top_x-small"> <img src={thumbnail} alt={file.title} onclick={filePreview} /> </a> <figcaption class="slds-file__title slds-file__title_card"> <div class="slds-media slds-media_small slds-media_center"> <lightning-icon icon-name={iconName} alternative-text={file.Title} title={file.Title} size="xx-small" > <span class="slds-assistive-text" >{file.Title}.{file.Extension}</span > </lightning-icon> <div class="slds-media__body slds-var-p-left_xx-small"> <span class="slds-file__text slds-truncate" title={file.Title} >{file.Title}.{file.Extension}</span > </div> </div> </figcaption> </figure> <div class="slds-is-absolute" style="top: 3px; right: 5px; z-index: 10"> <lightning-button-menu alternative-text="Show File Menu" variant="border-filled" icon-size="xx-small" > <lightning-menu-item value="preview" label="Preview" ></lightning-menu-item> <lightning-menu-item value="delete" label="Delete" ></lightning-menu-item> </lightning-button-menu> </div> </div> </li> </template> </template> |
PreviewFileThumbnailCard.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 | import { LightningElement, api } from "lwc"; export default class PreviewFileThumbnailCard extends LightningElement { @api file; @api recordId; @api thumbnail; get iconName() { if (this.file.Extension) { if (this.file.Extension === "pdf") { return "doctype:pdf"; } if (this.file.Extension === "ppt") { return "doctype:ppt"; } if (this.file.Extension === "xls") { return "doctype:excel"; } if (this.file.Extension === "csv") { return "doctype:csv"; } if (this.file.Extension === "txt") { return "doctype:txt"; } if (this.file.Extension === "xml") { return "doctype:xml"; } if (this.file.Extension === "doc") { return "doctype:word"; } if (this.file.Extension === "zip") { return "doctype:zip"; } if (this.file.Extension === "rtf") { return "doctype:rtf"; } if (this.file.Extension === "psd") { return "doctype:psd"; } if (this.file.Extension === "html") { return "doctype:html"; } if (this.file.Extension === "gdoc") { return "doctype:gdoc"; } } return "doctype:image"; } filePreview() { console.log("###Click"); const showPreview = this.template.querySelector("c-preview-file-modal"); showPreview.show(); } } |
PreviewFileModal.html
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 | <template> <template if:true={showModal}> <section role="dialog" tabindex="-1" aria-labelledby="modal-heading-01" aria-modal="true" aria-describedby="modal-content-id-1" class="slds-modal slds-fade-in-open" > <div class="slds-modal__container"> <!-- Header Start --> <header class="slds-modal__header"> <lightning-button-icon class="slds-modal__close" title="Close" icon-name="utility:close" icon-class="slds-button_icon-inverse" onclick={closeModal} ></lightning-button-icon> <h2 id="id-of-modalheader-h2" class="slds-text-heading_large"> File Preview </h2> </header> <!-- Header End --> <div class="slds-modal__content" id="modal-content-id-1"> <lightning-layout> <lightning-layout-item flexibility="auto"> <article class="slds-card"> <div class="slds-card__body slds-card__body_inner" style="margin: 0" > <template if:false={showFrame}> <img src={url} /> </template> <template if:true={showFrame}> <iframe src={url} style="width: 100%; height: 800px" ></iframe> </template> </div> </article> </lightning-layout-item> </lightning-layout> </div> <footer class="slds-modal__footer slds-grid slds-grid_align-spread"> <lightning-button variant="brand-outline" label="Cancel" onclick={closeModal} title="Cancel" class="slds-var-m-left_x-small" ></lightning-button> </footer> </div> </section> <div class="slds-backdrop slds-backdrop_open"></div> </template> </template> |
PreviewFileModal.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | import { LightningElement, api } from "lwc"; export default class PreviewFileModal extends LightningElement { @api url; @api fileExtension; showFrame = false; showModal = false; @api show() { console.log("###showFrame : " + this.fileExtension); if (this.fileExtension === "pdf") this.showFrame = true; else this.showFrame = false; this.showModal = true; } closeModal() { this.showModal = false; } } |
PreviewFileModal.css
1 2 3 4 | .slds-modal__container { width: 90% !important; max-width: 90% !important; } |
FileController.cls
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | public with sharing class FileController{ @AuraEnabled(cacheable=true) public static List<ContentVersion> getVersionFiles(String recordId){ try { return [ SELECT Id, Title, ContentDocumentId, FileType, ContentSize, FileExtension, VersionNumber, CreatedDate, VersionData, FirstPublishLocationId FROM ContentVersion WHERE FirstPublishLocationId =:recordId ORDER BY CreatedDate DESC ]; } catch (Exception e) { throw new AuraHandledException(e.getMessage()); } } } |
Output
Checkout the complete tutorial below
11 Comments
Added data-id = contentDocumentId on the div as an attribute
ReplyDelete"div class="slds-file slds-file_card slds-has-title" style="width: 14rem" data-id={file.ContentDocumentId}
onclick={previewHandler}>
"
, but when fetching it in the onclick function as e.target.dataset.id its coming as undefined, even though i can see the value is populated correctly in html.
console.log(event.target.dataset.id)
undefined.
Any idea why ?
Got it to work. Used event.currentTarget.dataset.id instead event.target.dataset.id
DeleteAwesome, thanks for sharing it here !
Deleteis this approach also applicable for .docx file ?
ReplyDeletebecause when i'm following this , the .docx files are getting downloaded even though i have changed the security setting
Same question
DeleteHello there, I believe browsers do not supports word preview as of now. However if you would like to display the preview of your word file you can do it using Google Documents' Viewer via an iframe
DeleteFor example in above code you can modify the downloadUrl in PreviewFileThumbnails.js file as shown below to get the result.
downloadUrl:
"https://docs.google.com/gview?url=https://speed-dream-9269-dev-ed.scratch.lightning.force.com/sfc/servlet.shepherd/document/download/" +
this.fileList[i].ContentDocumentId +
"&embedded=true"
Hey Kapil , although i wanted to change docx file in pdf and then preview it using VF page . but there is also a limitation with render as for docx file
DeleteYeah I got one
ReplyDeleteI have a file from AWS S3, how can I display/preview it in Salesforce? The URL is stored in Salesforce, need to display it as a preview. Used the above approach but the preview is not being displayed but the pdf is getting downloaded even after changing the settings as suggested
ReplyDeleteHow to avoid showing the download icon in the modal displaying pdf ?
ReplyDeleteHi
ReplyDeleteI am able to preview img/pdf files, but how I will be able to preview doc files ?