Generate several invoices with just a single click using TypeScript

I'm interested in efficiently printing multiple custom HTML invoices with just one click, similar to this example:

https://i.sstatic.net/hAQgv.png

Although I attempted to achieve this functionality using the following method, it appears to be incorrect as it prompts the print dialog multiple times:

printInvoices() {
    this.orders.forEach(order => {
      let content = `
      <head>
    <link href="https://cdn.jsdelivr.net/npm/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="395b56564d4a4d4b4b2f6669666562612763040c55010104063e">[email protected]</a>/dist/css/bootstrap.min.css" rel="stylesheet"
        integrity="sha384-GLhlTQ8iRABdZLl6O3oVMWSktQOp6b7In1Zl3/Jr59b6EGGoI1aFkw7cmDA6j6gD" crossorigin="anonymous">
    <style>
        @media print {
            .invoice {
                font-size: 11px !important;
                overflow: hidden !important
            }
        }
    </style>
</head>

<body>
—

</body>
      `;

      let newWindow = window.open("", "", "width=300,height=300");
      newWindow?.document.write(content);
      newWindow?.focus();
      newWindow?.print();
      newWindow?.close();
    });
  }

Any suggestions on how to accomplish this task more effectively?

Answer №1

If you want to display all your invoices on one page in blocks, you can achieve this by using the CSS property page-break-after: always; to split these blocks into multiple pages.

Here's an example:

document.getElementById('printBtn').addEventListener('click', () => {
  window.print();
});
.pages {
  display: none;
}

@media print {
  #printBtn {
    display: none;
  }
  @page {
    margin: 0;
  }
  .pages {
    page-break-after: always;
    display: block;
  }
}
<div class="container">
  <div class="pages">
    <h1>One</h1>
  </div>
  <div class="pages">
    <h1>Two</h1>

  </div>
  <div class="pages">
    <h1>Three</h1>
  </div>
</div>

<button id="printBtn">Print me</button>

Using multiple instances of window.print() will trigger the print dialog multiple times for each block created.

Answer №2

Chances are, the best way to tackle this issue is by combining several PDFs directly on the server and then printing the consolidated document in one go.

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

yii2: Utilizing the power of dynamic calling in widgets

Imagine I have a widget called Widget1; In the view file, I call this widget like so: <?= Widget1::widget() ?> Clicking on an element should trigger a new instance of the widget and execute its JavaScript scripts. However, I am unable to get the s ...

What are some methods for saving HTML form data locally?

Creating an HTML form and seeking a solution for retaining user data even after closing and reopening the window/tab. Utilizing JavaScript cookies or HTML 5 local storage would require writing code for every input tag, which could be time-consuming especi ...

Comparison of HTML's equivalent to LaTeX's label and ef functionality

I have a Frequently Asked Questions page coded in HTML (example) where the questions often refer to one another. This results in the numbering changing whenever we add, delete, or rearrange the questions. LaTeX provides an elegant solution to this problem ...

Subscribe to a new Observable once the previous one completes

I need assistance in getting the current user after logging in. When I use this.router.navigate([this.returnUrl]); it does not work. Can someone please help me identify what is wrong here and how I can fix it? onSubmit(): void { this.authService.logi ...

The utilization of rxjs' isStopped function is now considered

We currently have this method implemented in our codebase: private createChart(dataset: any): any { if (!this.unsubscribeAll.isStopped) { this.chart = this.miStockChartService.createChart(dataset, this.chartId, this.options, this.extend ...

Encountering an error when using setState with React.createElement: invalid type provided

https://i.sstatic.net/YHssU.png Anticipated Outcome Upon clicking the login button without inputting an email or password, the user is expected to view the Notification component. Actual Outcome Upon clicking the login button, the setState function is ...

Styling a parent element when it is in focus using CSS3

Is there a way to apply a style to the parent element when an input is in focus? input:focus { background-color:yellow; } For example, if we have the following HTML: <div class="foo"> <input type="text /> Hello </div> I ...

My goal is to utilize CSS grid to craft a unique layout by establishing a grid area. However, the layout is not functioning as anticipated

Currently, I am in the process of mastering CSS grid layout design. If you are curious to see my progress so far, check out this Codepen link showcasing my code. Additionally, for a visual representation of the layout, feel free to view the layout image ...

How to automatically select the first item in a populated dropdown list using Vue JS

My HTML select element is populated with options from a server, but when using v-model, it initially selects an empty option instead of the first one. I came across a solution on a post which suggests selecting the first option manually, but since the dat ...

Implementing reCAPTCHA in Spring MVC with Ajax

I've been attempting to implement Google reCAPTCHA service with Spring MVC, but I keep encountering this error in the console: http://localhost:8080/spapp/ajaxtest.htm?name=frfr&surname=frfr&phone=edede…nGi3CCrD9GprYZDn8VHc-pN--SK-u_xoRKOrn ...

Adjust the dimensions of the canvas without disrupting the existing artwork

I am currently working on a pixel art application where I am facing an issue with saving images from the canvas. The saved image appears small and pixelated when I try to resize it. I would like to resize the image to larger dimensions, but I am unsure of ...

Exploring a personalized approach to searching in DataTables

I am facing a dilemma with implementing a custom search in a DataTables table due to my limited experience with JavaScript. The function I have only triggers on startup and not when typing in the search box. If you're interested, you can find my orig ...

Using the RabbitMQ consume method in conjunction with the channel.ack function

I'm currently working on a function in TypeScript to consume messages from my RabbitMQ: async consume( queue: string, callback: (message: ConsumeMessage | null) => void, ) { return this.channel.consume(queue, message => { c ...

Deciphering Google location data using JavaScript

It appears that this code is not functioning properly for unknown reasons let url = "https://maps.googleapis.com/maps/api/place/search/json?"; url += "location="+lat+","+lng+"&"; url += "radius=500&"; url += "types=&"; url += "name=&"; url ...

Express JS redirect does not update the URL and fails to load static files

I'm currently developing an application using Express.js to build the REST interface on Node.js. Additionally, I am using jQuery Mobile for the client-side pages. One issue I am facing is with redirects when users try to access a restricted or inacce ...

What is the best way to implement global error handling for NextJS API requests?

Is there a method to set up a Global error handler that captures the stack trace of errors and sends it to an external system like NewRelic without needing to modify each individual API? This would follow the DRY principle by avoiding changes to multiple ...

Node.js UDP broadcast to subnet not working properly in Linux

Here is a simplified Node JavaScript code snippet for testing purposes. Click here to view the code on GitHub This code creates a socket for each interface address, calculates the subnet broadcast address, and then sends data every second for 4 seconds t ...

The 'isLoading' property is not found in the type 'UseMutationResult<AxiosResponse<any, any>, Error, void, unknown>'.ts(2339)

I'm currently working on implementing a delete functionality that displays a loading state using the useMutate function from tanstackquery. However, I encountered an issue where the loading state is not shown when I click the delete button, even after ...

The initial child expands in width according to the content until it reaches the boundaries of the parent, triggering the

My goal is to achieve a layout where the parent container's width can vary. The first child element (red) should expand based on its content until it reaches the end of the parent, at which point text-overflow: ellipses should be applied. The second c ...

Angular - Implementing service worker to extract dynamic ID from route in "Notificationclick" event?

I have integrated push notifications into my code to notify users when an action is taken. The backend was developed using lib.net.webpush 3.1.0 with .net 4.5.2 in C#. The notification system is functioning well, but I am facing a challenge: Within my ser ...