0

I'm new to Salesforce development and currently try to render a PDF that has been generated with jsPDF in a modal (i.e., I managed to generate PDFs from an LWC using jsPDF, yet I'd like to render it using a PDF viewer). Equipping the PDF viewer with download and email buttons would be great, since I'd like to replace the standard "Create PDF" button.

I followed the discussions here and here.

My test html looks as follows:

<template>
    <!-- lightning button for open modal window -->
    <lightning-button variant="brand"
       label="Create PDF (DE)"
       title="Create PDF (DE)"
       onclick={openModal}
       class="slds-m-left_x-small">
    </lightning-button>
    <!--Use template if:true to display/hide popup based on isModalOpen value--> 
    <template if:true={isModalOpen}>
        <!-- Modal/Popup Box LWC starts here -->
        <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" style="width: 90% !important; max-width: 100rem">
                <!-- Modal/Popup Box LWC header here -->
                <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"
                            variant="inverse"
                            size="small" ></lightning-icon>
                        <span class="slds-assistive-text">Close</span>
                    </button>
                    <h2 id="modal-heading-01" class="slds-text-heading_medium slds-hyphenate">Create Quote PDF in German</h2>
                </header>
                <!-- Modal/Popup Box LWC body starts here -->
                <div class="slds-modal__content slds-p-around_medium" style="height: 85%" id="modal-content-id-1">
                 <iframe id="pdfFrame" src="/resource/pdfjs/web/viewer.html?file=" width="100%" height="100%" class="pdfFrame" onload={generatePdf}></iframe>
                </div>
                <!-- Modal/Popup Box LWC footer starts here -->
                <footer class="slds-modal__footer">
                    <button class="slds-button slds-button_neutral" onclick={closeModal} title="Cancel">Cancel</button>
                    <button class="slds-button slds-button_brand" onclick={submitDetails} title="OK">OK</button>
                </footer>
            </div>
        </section>
        <div class="slds-backdrop slds-backdrop_open"></div>
    </template>
 </template>
</template>

The js:


import {LightningElement, track} from 'lwc';
import {loadScript} from "lightning/platformResourceLoader";
import JSPDF from '@salesforce/resourceUrl/jspdf';

export default class CreateQuote extends LightningElement {
    //Boolean tracked variable to indicate if modal is open or not default value is false as modal is closed when page is loaded 
    @track isModalOpen = false;
    
    openModal() {
        // to open modal set isModalOpen track value as true
        this.isModalOpen = true;
        //this.generateData();
    }
    closeModal() {
        // to close modal set isModalOpen track value as false
        this.isModalOpen = false;
    }
    submitDetails() {
        // to close modal set isModalOpen track value as false
        //Add your code to call apex method or do some processing
        this.isModalOpen = false;
    }

    renderedCallback() {
        Promise.all([
            loadScript(this, JSPDF)
        ]);
    }

    generatePdf(){
        const { jsPDF } = window.jspdf;
        const pdf = new jsPDF({
            encryption: {
                userPermissions: ["print", "modify", "copy", "annot-forms"]
            }
        });

        pdf.text("Hello World", 20, 20);
        console.log(pdf.output('datauristring'));

        this.template.querySelector('iframe').contentWindow.postMessage(pdf.output('datauristring').split(',')[1], window.location.origin);
    }
}

Here's a screenshot of the empty viewer: enter image description here

If I remove the ?file= from the iframe:

<iframe id="pdfFrame" src="/resource/pdfjs/web/viewer.html" width="100%" height="100%" class="pdfFrame" onload={generatePdf}></iframe>

pdfjs viewer shows the default document (delivered with pdfjs): enter image description here

However, the following is not clear to me:

Thanks for your help!

1 Answer 1

1

I am able to answer this as I have answered on both of those and I have recently developed exactly what you are trying to do.

Where does "/resource/pdfjs/web/viewer.html" come from? What do I need to install and how?

  • You can get Pdfjs here
  • Once you download it, load that as a Static resource in Setup > Static resources (you can load a zip file too, SF unzips it automatically), refer to this trailhead to learn more about how to use static resources
  • viewer.html is part of PDFJs library which you can access by using /resource/pdfjs/web/viewer.html where pdfjs is the API name of your static resource.

Because you are directly passing your viewer.html as iFrame source, you do not need to use loadScript().

To show PDF in your iFrame, you can display text like you are doing or you can pass your base64data in this line :

this.template.querySelector('iframe').contentWindow.postMessage(this.pdfData, window.location.origin);

Also, add a lightning-button that you can click and invoke your generateData() to see if your pdf viewer UI is showing, that gives you confirmation that the PDFJS resource is being loaded successfully.

To download you basically need to generate download link for browser behind the scene and click on it.

<lightning-button variant="brand-outline" label="Download" title="Primary action" onclick={downloadPdf} ></lightning-button>

JS :

downloadPdf(event){
    
    let downloadLink = document.createElement("a");
    downloadLink.setAttribute("type", "hidden");
    downloadLink.href = "data:application/octet-stream;base64,"+this.pdfData;
    downloadLink.download = "PDF NAME".pdf";
    document.body.appendChild(downloadLink);
    downloadLink.click();
    downloadLink.remove();
        
}

Let me know if this helps and answers your question. Happy to help further if you are stuck.

3
  • Comments are not for extended discussion; this conversation has been moved to chat.
    – David Reed
    May 17, 2021 at 13:32
  • I am running into a problem while trying to use the same PDF.js library. Posted a question about it at salesforce.stackexchange.com/questions/354812/…. Would love to have some guidance regarding the it.
    – N_H1922
    Aug 24, 2021 at 6:59
  • How did pdf.text("Hello World", 20, 20); convert into a nice looking pdf with all those text? How do I get the actual content from an lwc component to 'pdf format'? I saw answers with pdf.fromHTML() but it didnt work. Tried this.template.querySelector('.pdfContent'); but didnt work as well. Jan 16 at 18:28

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.