The CreatorCon Call for Content is officially open! Get started here.

ohhgr
Kilo Sage

      Using a bit fancy HTML features is almost common in ServiceNow. It helps to arrange information in a simpler and more organized manner. It also allows us to draw the attention to the important statistics right away. It can be leveraged to create a tabular format or even use the advanced CSS skills and create a different format to show the information. However, as it happens, once such a custom UI is built to showcase the information, more often than not, the response we hear is, "Ohh this looks great. But, can we print this?" And certainly most often the reaction the developer has is this...

 

via GIPHY

      ServiceNow has a plugin called as PDFGenerator, it is an amazing plugin that helps build PDF from ServerSide code using iTextPDF. However, as of pre-Paris, it does suffer from some limitations like lack of support for CSS and fonts. (Some of this has been addressed in Paris release). And even if we decide to use it, we need to interact with Server to generate the PDF. And that prompted me to look for some Javascript alternatives. And that search brought me to a brilliant library - HTML2PDF by Erik Koopmans.

      One of the advantages I found with the library is it accepts an HTML Element as a parameter. It then converts that HTML Element content to the canvas and then to an image and prints as a PDF. (If you want your PDF to be editable/searchable for text, this isn't for you. 😞 ). It served the purpose of printing a PDF with some custom CSS and different fonts in my case.As per the documentation on the homepage, the typical flow of the data looks as below.

.from() -> .toContainer() -> .toCanvas() -> .toImg() -> .toPdf() -> .save()

      Using the library is very easy. You can use it as a dependency on your widget or can simply include the reference in your UI Page. To see how it works, we can use a simple static page today. We will create a resume for my alter-ego, Aalshi Boka. 😉 To get started, let's create a new UI Page, give it a meaningful name. I'm going to name it "AalshiBokaResume". Mark the "Direct" checkbox, this tells ServiceNow not to load its standard header (HTML), styling (CSS) and JavaScript (script dependencies). Then copy below CSS/HTML content in its HTML section.

<html>
	<head>
		<style>
			.resume-container {
			max-width: 700px;
			}

			.resume {
			display: flex;
			flex-direction: row;
			align-items: space-around;
			justify-content: space-around;
			}

			.column-1 {
			display: flex;
			flex-direction: column;
			background-color : #839b97;
			align-items: flex-start;
			padding: 10px;
			margin: 0 10px 0 0;
			width: 250px;
			}

			.column-2 {
			display: flex;
			flex-direction: column;
			align-items: center;
			max-width: 450px;
			}

			.profile-pic {
			height: 200px;
			width: 200px;
			border-radius: 50%;
			}

			.header-1 {
			background-color: #34626c;
			padding: 5px;
			width: 200px;
			}

			.education {
			padding: 0 0 0 25px;
			}

			.profile-details {
			height: 200px;
			background-color: #34626c;
			width: 100%;
			text-align: center;
			}

			.name {
			font-size: 48px;
			margin-bottom: 0px;
			}

			.title {
			font-size: 24px;
			margin-top: 0px;
			}
			
			.list {
			padding: 0 0 0 25px;
			margin: 5px 0 5px 0;
			}

			.header-2 {
			font-size: 20px;
			font-weight: bold;
			}

			.exp-title {
			font-weight: bold;
			}

			.print {
			text-align: center;
			}
		</style>
	</head>
	<body>
		<div class="resume-container">
			<script src="https://raw.githack.com/eKoopmans/html2pdf/master/dist/html2pdf.bundle.js"></script>
			<div class="resume" id="resume">
				<div class="column-1">
					<img src="/AalashiBoka.jpg" class="profile-pic" />
					<div>
						<p class="header-1">Education</p>
						<p class="education">Bachelors in Sleeping<br/>
							Lazy University<br/>
							2006-2010</p>
					</div>
					<div class="skills">
						<p class="header-1">Skills</p>
						<p class="list">- Purring<br/>
							- Deep slumber<br/>
							- Half-Eye Shut Sleep<br/>
							- Sleeping Belly-up<br/>
							- Loafing</p>
					</div>
					<div class="certification">
						<p class="header-1">Certifications</p>
						<p class="list">- Certifications<br/>
							- Certified Lucid Dreamer<br/>
							- Sleep Master Certified<br/>
							- ISLEEP v3 Foundation</p>
					</div>
				</div>
				<div class="column-2">
					<div class="profile-details">
						<p class="name">Aalshi Boka</p>
						<p class="title">Sleep Enthusiast</p>
					</div>
					<div class="about">
						<p class="header-2">Profile</p>
						<p>I am a sleep entusiast with over 10 years of experience in sleeping. I have devised several new ways of sleeping in boxes and buckets. I am very passionate about sleeping patterns and regularly contribute to the well-sleeping of my team.</p>
					</div>
					<div class="experience">
						<p class="header-2">Professional Experience</p>
						<p class="exp">
							<p class="exp-title">Sleeping Architect, Bedtime Stories Ltd. (2015 - till date)</p>
							<p class="list">
								- Designing sleep patterns for the team<br/>
								- Leading a team of more than five cats<br/>
								- Ensuring sleeping standards are maintained<br/>
								- Mentoring and grooming kittens
							</p>
							<p class="exp-title">Senior Sleep Consultant, Laziness Inc. (2010 - 2015)</p>
							<p class="list">
								- Helping clients to sleep better<br/>
								- Utilizing my experience to the fullest potential<br/>
								- Ensuring cats take sleep seriously in the office<br/>
								- Facilitating use of the usual items like pillow, cushion to sleep<br/>
								- Innovative use of props like boxes, buckets, tables to create new sleeping locations
							</p>
						</p>
					</div>
				</div>
			</div>
			<div class="print">
				<button onClick="printPDF()">Print</button>
			</div>
		</div>
	</body>
</html>

 

      In this case, since we're more interested in checking the functionality of the library than managing the content, we're using the hard-coded values. Above code can easily be made dynamic if a similar functionality is to be extended from some ServiceNow database. As you can see, we are using a script tag in this case to load the dependency. As mentioned earlier, better way is to download the script, create a UI Page and refer to that UI Page. We're also using an image from the great Unsplash as the profile image for Aalshi Boka. Download the same from the site and upload under Images with the name - "AalashiBoka.jpg". Next step is to add the Client Script that instantiates the HTML2PDF object and creates a PDF.

function printPDF() {
	var element = document.getElementById('resume');
	// html2pdf(element);

	var opt = {
		margin:       1,
		filename:     'MyResume.pdf',
		image:        { type: 'jpeg', quality: 1 },
		html2canvas:  { scale: 4 },
		jsPDF:        { unit: 'in', format: 'A4', orientation: 'portrait' }
	};
	html2pdf().set(opt).from(element).save();
}

 

      We're passing the element with id "resume" to the html2pdf function. This functionality enables us to print only a certain part, certain section of the page as PDF rather than printing the whole page. We are also passing on certain parameters to this function. As we are not much worried about the quality of the image on PDF, hence we're using "jpeg" in our settings rather than more resource-consuming "png".More information about the parameters could be found at HTML2PDF site's homepage. 

 

find_real_file.png

 

      Once done, we're good with our task. Save the UI Page and click on "Try It" to render the resume for Aalshi Boka. You'd see a button at the bottom called "Print", click on it and the PDF will be downloaded for you. 🙂 Play around the options above and see if this library helps you to achieve any of your requirements.

Comments
Pranav Bhagat
Kilo Sage

This is nice ,Let me try it .

 

Thanks for sharing 🙂

ohhgr
Kilo Sage

🙂

rahulpandey
Kilo Sage

Great details  🙂

via GIPHY

 

Yup,

HTML2PDF is great, hookup with an HTML field and serves great 😄

Below are couple of elements not supported by itextPDF

  • Vertical alignment
  • Page breaks
  • Table-specific color (text color is supported)
  • Custom spacing between blocks of text or images
  • Custom column width in HTML tables
  • Custom column alignment in HTML tables
  • Custom border styling in HTML tables
  • CSS text manipulation (including CSS based font tags)
  • Inline styling
  • Background images
ohhgr
Kilo Sage

Great points @rahulpandey ..

 

However, HTML2PDF isn't the complete solution either. Each approach has its benefits and drawbacks, so a solution should be chosen based on the requirements at hand. 🙂

 

Version history
Last update:
‎11-22-2020 01:30 AM
Updated by: