Currently, my goal is to create PDFs using Angular

<button class="print" (click)="generatePDF()">Generate PDF</button>

Code to Generate PDF

generatePDF(): void {
    const element = document.getElementById('mainPrint') as HTMLElement;
    const imgWidth = 210;
    const pageHeight = 295;

    html2canvas(element, { scale: 2 }).then((canvas) => {
        const imgData = canvas.toDataURL('image/png');
        const pdf = new jsPDF();
        const imgHeight = (canvas.height * imgWidth) / canvas.width;
        let heightLeft = imgHeight;
        let position = 0;

        while (heightLeft >= 0) {
            position = heightLeft - pageHeight;
            pdf.addImage(imgData, 'PNG', 0, position, imgWidth, imgHeight);
            heightLeft -= pageHeight;
            if (heightLeft > 0) {
                pdf.addPage();
            }
        }

        pdf.save('page.pdf');
    });
}

Upon clicking the "Generate PDF" button, a PDF is produced. However, the initial 4-5 pages are appearing blank, with content only showing from the subsequent pages but not fully displayed.

Answer №1

I have successfully removed the extra space, although it may not be flawless. Perhaps you can enhance it further from here!

import { CommonModule } from '@angular/common';
import { Component } from '@angular/core';
import { bootstrapApplication } from '@angular/platform-browser';
import 'zone.js';
import { ChildComponent } from './child/child.component';
import html2canvas from 'html2canvas';
import jsPDF from 'jspdf';

@Component({
  selector: 'app-root',
  standalone: true,
  imports: [CommonModule, ChildComponent],
  template: `
  <div id="mainPrint">
  <app-child/>
  </div>
    <button class="print" (click)="generatePDF()">Generate PDF</button>
  `,
})
export class App {
  name = 'Angular';

  generatePDF(): void {
    const element = document.getElementById('mainPrint') as HTMLElement;

    html2canvas(element, { scale: 2 }).then((canvas: any) => {
      var imgData = canvas.toDataURL('image/png');

      var imgWidth = 210;
      var pageHeight = 295;
      var imgHeight = (canvas.height * imgWidth) / canvas.width;
      var heightLeft = imgHeight;
      var doc = new jsPDF('p', 'mm', 'a4'); // landscape
      var position = 0;

      /* addImage explained below:
          param 1 -> image in code format
          param 2 -> type of the image. SVG not supported. needs to be either PNG or JPEG.
          all params are specified in integer
          param 3 -> X axis margin from left
          param 4 -> Y axis margin from top
          param 5 -> width of the image
          param 6 -> height of the image
      */

      doc.addImage(imgData, 'JPEG', 0, 0, imgWidth, imgHeight);
      heightLeft -= pageHeight;

      while (heightLeft >= 0) {
        position = heightLeft - imgHeight;
        doc.addPage();
        doc.addImage(imgData, 'JPEG', 0, 0, imgWidth, imgHeight);
        heightLeft -= pageHeight;
      }

      doc.save('page.pdf');
    });
  }
}

bootstrapApplication(App);

Visit stackblitz demo for more details.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Issue encountered while attempting to load several google charts simultaneously

What do I need? I am in need of two Google charts, one on each tab of the website as shown in the screenshot below: Tabs What seems to be the issue? The second chart is not loading properly and showing mixed information. This can be observed in the scre ...

Subscription to Observable content failed to run

When a submit button is clicked inside the component HTML, it triggers a function called addCollaborators(). The code for this function can be found below: component.ts emails: string[] = []; constructor(public userService: UserService) {} // Function ...

Displaying the product quantity counter in the shopping cart immediately after adding the item

My website has a shopping cart quantity counter that doesn't update immediately when a product is added. Instead, it requires a page reload or navigation to another page for the change to be reflected. I would like the quantity counter to show the pro ...

What would the equivalent Javascript implementation look like for this Python code that decodes a hex string and then encodes it to base64?

Currently, I am facing the challenge of transferring code from a Python script that decodes and encodes a string using a series of decode() and encode() functions. In Python, the code appears as follows: import codecs input = '3E061F00000E10FE' ...

Using NextJs to track the position of a scrollbar

Incorporating NextJs for Server Side Rendering has been a game-changer for me. I've also implemented a navbar in my application that needs to adjust styles based on the scroll position. Is there a way to determine if the window has scrolled beyond 100 ...

Managing Prisma error handling in Express

Dealing with error handling using ExpressJS and Prisma has been a challenge for me. Anytime a Prisma Exception occurs, it causes my entire Node application to crash, requiring a restart. Despite looking at the Prisma Docs and doing some research online, I ...

Show the contents of a JSON file using Vue

I have a JSON file containing some data that needs to be fetched and displayed in a component. In the actions of my Vuex store, I've implemented: async getTodos (context) { const todos = [] const response = await fetch('../../data/todos.jso ...

Angular 2 child route causing application to become unresponsive

Hey there, I'm currently working on setting up child routes for my Angular app and this is what I have so far: import {bootstrap} from 'angular2/platform/browser' import {CommercifyComponent} from './commercify.component' import { ...

AngularJS does not support the use of $(this) syntax

I have encountered an issue while developing a Chrome extension using AngularJS. I would like to add buttons to my popup page, and I want the ancestor node to disappear when a button is clicked. Here is the code snippet: in popup.html <div class="dea ...

Troubleshooting: How to resolve the issue of "Error [ERR_HTTP_HEADERS_SENT]: Unable to set headers after they have been sent to the client"

* **> const PORT=8000 const express = require('express') const {v4:uuidv4}=require('uuid') const bcrypt =require('bcrypt') const jwt =require('jsonwebtoken') const cors=require('cors') const {MongoClie ...

How to Properly Retrieve an Array of JSON Objects Using Ionic 3 Storage

Storing and retrieving an array of JSON objects locally with Ionic storage: Country[5] 0: {record_id: "1", local_TimeStamp: "16:00:00", country: "USA"} 1: {record_id: "2", local_TimeStamp: "17:00:00", country: "Japan"} 2: {record_id: "3", local_TimeStamp: ...

Move the modal dialog so it appears closer to the top of the page

I am facing a challenge with my jQuery modal dialog. While it is loading properly, I am restricted to using an older version of jQuery (1.12.4) and cannot upgrade it. My goal is to center the modal close to the top of the page, similar to how it is positio ...

In Node.js, the mongodb+srv URI does not support including a port number

Currently, I am working on a project in nodejs using express js. I have encountered the following error: MongoDB connection error: MongoParseError: MongoDB+srv URI cannot contain a port number. In my "MongoDB Atlas" dashboard, I have obtained my "connecti ...

How can a "Loading" message be displayed while external JavaScript is loading?

I have mastered the art of using JS or jQuery to showcase a "Loading" message during the loading process. Currently, I am working on a sizeable web application that relies on various JS dependencies, and I am seeking a way to exhibit a "loading" message wh ...

The rule "react/jsx-sort-props" does not have a valid configuration

I've been attempting to organize props names alphabetically using the eslint-plugin-react plugin but I keep encountering this error: [Error ] .eslintrc.json: Configuration for rule "react/jsx-sort-props" is invalid: Value {"callbacksLast":true,"shorth ...

Using Vue.js and JavaScript to access a single variable across multiple class methods

I am working on organizing my custom channel logic into its own class. During the created lifecycle method, I am executing each method in the class I created. However, I am facing a challenge in retaining the instance of the socket that was created in the ...

The second AJAX call is unsuccessful

I have created a dynamic ajax website that retrieves pages from the /pages folder and displays them within an ajax-container div on my index.php. Now, I am looking to implement a second ajax request that will only be triggered on certain pages. For examp ...

Relaunch jQuery script on dynamically loaded content via AJAX requests

Currently, I am utilizing the Advanced Ajax Page Loader plugin for wordpress to dynamically load content through ajax. However, I am encountering an issue where my custom jquery scripts do not execute properly when the content is loaded via ajax. Interesti ...

Different options for reading large files during an AJAX file upload

It seems that php's file_get_contents is not able to handle large files. What can be done as an alternative if it is causing a "stack overflow" issue? HTML File <form id='test'> <input type='file' name='Receipt&ap ...

Using Angular, create mat-checkbox components that are dynamically generated and bound using

In my Offer class, I have a property called "units" which is an array of objects. export class Offer { public propertyA: string; public propertyB: string; public units: Unit[]; } export class Unit { public code: string, public name: ...