Print Component with Laravel Blade and AlpineJS

Print Component with Laravel Blade and AlpineJS

Written by Mithicher Baro on Jan 17th, 2022 Views Report Post

First and foremost, I want to wish everyone a very Happy New Year 2022.

Recently, while working on a Laravel-based project, I encountered a scenario in which I needed to print a section of the page when a button was pressed.

After some searching, I came across the following Stackoverflow solution or snippet:

https://stackoverflow.com/questions/468881/print-div-id-printarea-div-only by Kevin Florida

The code mentioned in the solution is as follows:

<div id="printableArea">
    <h1>Printable Content Goes Here...</h1>
</div>

<input type="button" onclick="printableDiv('printableArea')" value="print a div!" />
function printableDiv(printableAreaDivId) {
     var printContents = document.getElementById(printableAreaDivId).innerHTML;
     var originalContents = document.body.innerHTML;

     document.body.innerHTML = printContents;

     window.print();

     document.body.innerHTML = originalContents;
}

The code above accomplishes the following:

  • When a button is pressed, it retrieves the content of the printable area and stores it in a variable.
  • Retrieve the body's inner html and save it to a variable.
  • Then, replace the body's content with the targeted content
  • Then call window.print() to launch the Print Dialog Box available in browser
  • When the Print Dialog Box is closed, replace the body's content with the original content.

Let's now use Alpine.js and Laravel blade components to convert this piece of code into a reusable laravel blade component.

Learn Alpine.js and TailwindCSS - I bet you will love it!

I assume you have a basic laravel breeze application up and running.

Checkout this article:

https://devdojo.com/bobbyiliev/what-is-laravel-breeze-and-how-to-get-started

Initialize an Alpine.js

Create a file named html-print.blade.php inside the views/components directory

<div 
	x-data="{
		printDiv() {
			var printContents = this.$refs.container.innerHTML;
			var originalContents = document.body.innerHTML;
			document.body.innerHTML = printContents;
			window.print();
			document.body.innerHTML = originalContents;
		}
	}" 
	x-cloak
	x-ref="container"
	class="print:text-black relative"
>
  /* Absolute position print button */
  <div class="print:hidden absolute top-3 right-4">
    <button type="button" x-on:click="printDiv()">Print</button>
  </div>

  {{ $slot }}

</div>
  • x-data: starts an Alpine.js magic

  • printDiv: is a function which takes the contents inside of the printable div and replaces the content of the body with the content of printable div.

  • Inside the printable div we create an absolute position button. When this button is clicked we call the printDiv function.

How to use

Put the following component, along with the printable content, on any of your blade pages.

<x-html-print>
  <h1>Printable Content Goes Here...</h1>
</x-html-print>

Full Component

Feel free to try out the full component, which includes some additional features.

  • Adjustable Print Button Position
  • Sticky Header
<div 
	x-data="{
		printDiv() {
			var printContents = this.$refs.container.innerHTML;
			var originalContents = document.body.innerHTML;
			document.body.innerHTML = printContents;
			window.print();
			document.body.innerHTML = originalContents;
		}
	}" 
	x-cloak
	x-ref="container"
	class="print:text-black relative"
>
	@isset($printButton)
		{{ $printButton }}
	@else
		<div class="print:hidden absolute top-3 right-4">
			<button type="button" x-on:click="printDiv()" class="bg-opacity-50 text-gray-700 shadow-sm border px-2 py-1 rounded-md bg-white flex items-center"><svg xmlns="http://www.w3.org/2000/svg" class="-ml-1 mr-1 h-5 w-5 text-gray-600" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 17h2a2 2 0 002-2v-4a2 2 0 00-2-2H5a2 2 0 00-2 2v4a2 2 0 002 2h2m2 4h6a2 2 0 002-2v-4a2 2 0 00-2-2H9a2 2 0 00-2 2v4a2 2 0 002 2zm8-12V5a2 2 0 00-2-2H9a2 2 0 00-2 2v4h10z" /></svg>Print</button>
		</div>
	@endisset

	<table class="table-auto w-full">
		@isset($header)
      <thead>
        <tr>
          <td>
            {{ $header }}
          </td>
        </tr>
      </thead>
		@endisset
		 
		<tbody>
			<tr>
				<td>
					{{ $slot }}
				</td>
			</tr>
		</tbody>

		@isset($footer)
			<tfoot>
				<tr>
					<td>
						{{ $footer }}
					</td>
				</tr>
			</tfoot>
		@endisset
	</table>
</div>

Conclusion

For more information, check out the links below:

That's all for now, I hope you enjoyed it!

Comments (0)