npm i vue-html2pdf
App.vue
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 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 |
<template> <div> <!-- Form for user input --> <div> <label for="reportTitle">Enter Report Title:</label> <input type="text" v-model="reportTitle" id="reportTitle" placeholder="Enter a title" /> <label for="reportContent">Enter Content:</label> <textarea v-model="reportContent" id="reportContent" placeholder="Enter some content"></textarea> <label for="imageSelect">Select an Image:</label> <input type="file" @change="onImageChange" id="imageSelect" accept="image/*" /> <!-- HTML2PDF component with dynamic content --> <vue-html2pdf :show-layout="false" :float-layout="true" :enable-download="true" :preview-modal="true" :paginate-elements-by-height="1400" filename="dynamic-report" :pdf-quality="2" :manual-pagination="false" pdf-format="a4" pdf-orientation="landscape" pdf-content-width="800px" @progress="onProgress($event)" @startPagination="startPaginationHandler()" @hasPaginated="hasPaginatedHandler()" @beforeDownload="beforeDownloadHandler($event)" @hasDownloaded="hasDownloadedHandler($event)" ref="html2Pdf" > <section slot="pdf-content" class="pdf-content"> <!-- Render dynamic content --> <h1>{{ reportTitle || 'Default Title' }}</h1> <p>{{ reportContent || 'Default content goes here. This will automatically be split across pages if it is too long.' }}</p> <!-- Display the selected image with centering and size adjustments --> <div v-if="selectedImage" class="image-container"> <img :src="selectedImage" alt="Selected Image" /> </div> </section> </vue-html2pdf> <!-- Button to trigger PDF generation --> <button @click="generateReport">Generate PDF</button> </div> </div> </template> <script> import VueHtml2pdf from "vue-html2pdf"; export default { data() { return { reportTitle: "", // User input for title reportContent: "", // User input for content selectedImage: null, // Selected image for PDF }; }, methods: { // Method to trigger PDF generation using the component ref generateReport() { this.$refs.html2Pdf.generatePdf(); }, // Event handler for PDF generation progress onProgress(event) { console.log("Progress:", event); }, // Event handler when pagination starts startPaginationHandler() { console.log("Pagination started"); }, // Event handler after pagination is complete hasPaginatedHandler() { console.log("Pagination completed"); }, // Event handler before downloading the PDF beforeDownloadHandler(event) { console.log("Before Download:", event); }, // Event handler after the PDF has been downloaded hasDownloadedHandler(event) { console.log("PDF Downloaded:", event); }, // Handle image file selection and convert to URL onImageChange(event) { const file = event.target.files[0]; if (file) { const reader = new FileReader(); reader.onload = (e) => { this.selectedImage = e.target.result; }; reader.readAsDataURL(file); } }, }, components: { VueHtml2pdf, }, }; </script> <style scoped> /* Global padding and margin for the entire PDF content */ .pdf-content { padding: 30px; /* Adds space around the content */ margin-left: auto; margin-right: auto; max-width: 100%; /* Ensure content doesn't overflow */ } /* Styling for text with equal margin on both sides */ h1, p { text-align: justify; margin-left: 30px; margin-right: 30px; line-height: 1.6; } /* Ensure long content breaks across pages correctly */ p { word-wrap: break-word; } /* Styling for the image, making it larger and centering it */ .image-container { text-align: center; margin-top: 20px; } img { max-width: 80%; /* Makes the image larger */ height: auto; margin-top: 10px; } </style> |