How to use a previewer from a Lightning Web Component

This tutorial shows an example on how to setup a Lightning Web Component that shows a preview, downloads the document and calls a Pack.

Prerequities:

This is the Apex class

The Apex will create the PDF and have a separate method to call a pack. Test class is also provided

                    
global class CallPdfButlerWithPreviewController {

    @AuraEnabled
    global static String convert(Id recordId) {

        //see https://www.pdfbutler.com/files/api/cadmuscore/ConvertController.html#ConvertController.convertWithWrapper

        cadmus_core.ConvertController.ConvertDataModel cdm = new cadmus_core.ConvertController.ConvertDataModel();
        cdm.objectId = recordId; //this must be the Id of the record you want to generate from eg an Opportunity Id

        //Select the DocConfig via the "cadmus_core__CustomerDocumentConfigId__c", this is unique over all sandboxes and PROD. So we can hardcode it
        cadmus_core__Doc_Config__c dc = [SELECT Id FROM cadmus_core__Doc_Config__c
                                         WHERE cadmus_core__CustomerDocumentConfigId__c = 'a6a612df-b30a-41aa-aa09-38119d42e904'];

        cdm.docConfigId = dc.Id;

        cadmus_core.DocGenerationWrapper wrapper = cadmus_core.ConvertController.convertWithWrapper(cdm);

        //Here we put the title and the base64 into a JSON. For demo purposes, we string-concatenate the JSON together.
        //Do not forget to use "EncodingUtil.base64Encode" on the base64!
        return '{"title":"' + wrapper.response.metadata.targetName + '","base64":"' + EncodingUtil.base64Encode(wrapper.response.base64) + '"}';
    }

    @AuraEnabled
    global static String pack(Id recordId, String longPackId) {

        //see https://www.pdfbutler.com/files/api/cadmuscore/ConvertController.html#ConvertController.convertWithWrapper

        cadmus_core.ConvertController.ConvertDataModel cdm = new cadmus_core.ConvertController.ConvertDataModel();
        cdm.objectId = recordId; //this must be the Id of the record you want to generate from eg an Opportunity Id

        //Select the Pack via the "cadmus_core__Customer_Pack_Id__c", this is unique over all sandboxes and PROD. So we can hardcode it
        cadmus_core__Pack__c pack = [SELECT Id FROM cadmus_core__Pack__c
                                         WHERE cadmus_core__Customer_Pack_Id__c = :longPackId];

        cdm.packId = pack.Id;

        cadmus_core.ConvertController.convertWithWrapper(cdm);

        //For demo purposes, we do not care about the response
        return 'OK';
    }
}
                    
                
                    
@isTest
public class CallPdfButlerWithPreviewControllerTest {

    @testSetup
    static void testSetup() {
        //1 Create a new Salesforce record for isntance Contact
        Contact c = new Contact();
        c.FirstName = 'First';
        c.LastName = 'Last';
        c.Email = 'c_first_last@testexample.com';
        insert c;
        //2 Create docConfig
        cadmus_core__Doc_Config__c doc_config = new cadmus_core__Doc_Config__c();
        doc_config.cadmus_core__Document_Title__c = 'TEST';
        doc_config.Name = 'TEST_DOC_CONFIG';
        doc_config.RecordTypeId = Schema.SObjectType.cadmus_core__Doc_Config__c.getRecordTypeInfosByName().get('Main Word Document').getRecordTypeId();
        insert doc_config;

        doc_config.cadmus_core__CustomerDocumentConfigId__c = 'a6a612df-b30a-41aa-aa09-38119d42e904'; //MAKE SURE TO UPDATE THIS TO THE CORRECT "CustomerDocConfigId" YOU HAVE IN YOUR CUSTOM CLASS
        update doc_config;

        //3 Create Pack
        cadmus_core__Pack__c pack = new cadmus_core__Pack__c();
        pack.cadmus_core__Active__c = true;
        pack.cadmus_core__Migrated_Customer_Pack_Id_2__c = 'abc123';
        pack.cadmus_core__Leading_Doc_Config__c = doc_config.Id;
        pack.Name = 'test';
        insert pack;
    }

    @isTest
    static void testConvert() {
        Contact c = [SELECT Id FROM Contact LIMIT 1];

        cadmus_core.CadmusHttpCalloutMock.setTestCalloutMockSuccess(c.Id);
        Test.startTest();

		CallPdfButlerWithPreviewController.convert(c.Id);
        Test.stopTest();
    }


    @isTest
    static void testPack() {
        Contact c = [SELECT Id FROM Contact LIMIT 1];

        cadmus_core.CadmusHttpCalloutMock.setTestCalloutMockSuccess(c.Id);
        Test.startTest();

		CallPdfButlerWithPreviewController.pack(c.Id, 'abc123');
        Test.stopTest();
    }
}
                    
                

The Lightning Web Component

LWC - HTML:

                
<template>
    <lightning-card class="c-lwc_generate-and-upload-document" variant="Narrow" title="PDF Butler - Custom Previewer" icon-name="standard:document_reference">
        <lightning-spinner if:true={spinner}></lightning-spinner>
        <div class="slds-p-horizontal_small">
            <p>Let's preview a generated Document!</p>
        </div>
        <div slot="footer" class="custom-foot">
            <lightning-button label="Generate Document" onclick={openModal}></lightning-button>
        </div>
    </lightning-card>

    <!--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={modalClass}>
            <div class="slds-modal__container">
                <!-- 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">
                        <img src={logoImageURL} />&nbsp;PDF Butler Document Preview
                    </h2>
                </header>
                <!-- Modal/Popup Box LWC body starts here -->
                <div class="slds-modal__content slds-p-around_medium" id="modal-content-id-1" style="height : 100% !important; max-height: 100% !important; ">
                    <iframe
                        src={iframeURL}
                        class="pdfFrame"
                        style="height: 98%; width: 100%; border: none">
                    </iframe>
                </div>
                <!-- Modal/Popup Box LWC footer starts here. Please change the name of Send an Email button based on your org pack -->
                <footer class="slds-modal__footer">
                    <button class="slds-button slds-button_brand" onclick={download} title="Download">Download</button>
                    <button class="slds-button slds-button_brand" onclick={runPack} title="Send an Email">Send an email</button>
                </footer>
            </div>
        </section>
        <div class="slds-backdrop slds-backdrop_open"></div>
    </template>
</template>
                
                

LWC - JavaScript Controller:

                
import { api,track,LightningElement } from 'lwc';
import { ShowToastEvent } from 'lightning/platformShowToastEvent';

import iframeResource from '@salesforce/resourceUrl/cadmus_core__PdfButlerPdfPreviewer';
import logoImageResource from '@salesforce/resourceUrl/cadmus_core__logo32x32';

import convert from '@salesforce/apex/CallPdfButlerWithPreviewController.convert';
import pack from '@salesforce/apex/CallPdfButlerWithPreviewController.pack';

export default class GenerateDocument extends LightningElement {

    @api recordId;
    @api logoImageURL = logoImageResource + '?';
    @api iframeURL = iframeResource + '/web/viewer.html#zoom=page-fit';
    @api modalClass = "slds-modal slds-fade-in-open slds-modal_large";

    // Title is set document title and base64 is set document data generated by Apex class
    @track title;
    @track base64;

    @track isModalOpen = false;

    openModal(event) {
        // to open modal set isModalOpen tarck value as true
        this.isModalOpen = true;

        // extecute Apex method when the modal is opened
        convert({recordId:this.recordId}).then((result)=>{
            this.title = result.title;
            this.base64 = result.base64;
            this.template.querySelector('iframe').contentWindow.postMessage(this.base64, '*');
        });
    }

    closeModal() {
        // to close modal set isModalOpen tarck value as false
        this.isModalOpen = false;
    }

    download(){
        // extecute download pdf file when click download button
        const linkSource = `data:application/pdf;base64,` + this.base64;
        const downloadLink = document.createElement("a");

        downloadLink.href = linkSource;
        downloadLink.download = this.title;
        downloadLink.click();
        downloadLink.remove();
    }

    runPack(){
        // extecute pack process when click Send an email button
        pack({recordId:this.recordId}).then(()=>{
            // show the notification about the process result
            this.showNotification('SUCCESS', 'The process was successfully completed!', 'success')
            })
            .catch(e => {
            this.showNotification('ERROR', 'The process ended abnormally. Contact your system administrator.', 'error')
            console.error(e)
        });
    }

    // the method to show the notification
    showNotification(title, message, variant) {
        const event = new ShowToastEvent({
            title: title,
            message: message,
            variant: variant,
        });
        this.dispatchEvent(event);
    }
}
                
                

LWC - Metadata:

                
<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>56.0</apiVersion>
    <description>PDF Butler Custom LWC Previewer</description>
    <isExposed>true</isExposed>
    <masterLabel>PDF Butler Custom LWC Previewer</masterLabel>
    <targets>
        <target>lightning__RecordPage</target>
    </targets>
</LightningComponentBundle>