Blog Post

How to edit PDFs using Angular

Illustration: How to edit PDFs using Angular
Information

This article was first published in May 2023 and was updated in October 2024.

In this blog post, you’ll learn how to edit a PDF document using Nutrient’s Angular PDF library. Developed and maintained by Google, Angular is an open source JavaScript framework. It’s written in TypeScript and follows a Model-View-Controller (MVC) design pattern.

Angular PDF library

We offer a commercial Angular PDF library that can easily be integrated into your web application. Our Angular viewer supports rendering PDF, JPEG, PNG, and TIFF in any modern browser and on any mobile device without any plugins.

It comes with 30+ features that let you view, annotate, edit, and sign documents directly in your browser. Out of the box, it has a polished and flexible user interface (UI) that you can extend or simplify based on your unique use case.

  • A prebuilt and polished UI
  • 15+ annotation tools
  • Cropping and rotation tools
  • Support for multiple file types
  • Dedicated support from engineers

Requirements

Information

No additional setup is required to use npm, as it’s included with your Node.js installation.

Project setup

To create a fresh Angular project and integrate Nutrient as a dependency, follow our getting started with Angular guide.

After you’ve completed the steps in the guide, you’ll have the following code in your app.component.ts file located at the src/app/ directory, and you’ll now be able to display a PDF document:

import { Component } from '@angular/core';
import PSPDFKit from 'pspdfkit';

@Component({
	selector: 'app-root',
	templateUrl: './app.component.html',
	styleUrls: ['app.component.css'],
	standalone: true,
})
export class AppComponent {
	title = 'PSPDFKit for Web Angular Example';

	ngAfterViewInit() {
		PSPDFKit.load({
			// Use the assets directory URL as a base URL. PSPDFKit will download its library assets from here.
			baseUrl: location.protocol + '//' + location.host + '/assets/',
			document: '/assets/Document.pdf',
			container: '#pspdfkit-container',
		}).then((instance) => {
			// For the sake of this demo, store the PSPDFKit for Web instance
			// on the global object so that you can open the dev tools and
			// play with the PSPDFKit API.
			(window as any).instance = instance;
		});
	}
}

The PSPDFKit.load() method creates a new Nutrient instance and returns a Promise resolving to a new PSPDFKit.Instance when supplied with a valid configuration object.

You can apply various edit operations to this PSPDFKit.Instance through the applyOperations(operations) method.

Information

If multiple operations are provided, each operation is performed on the resulting document from the previous operation.

Editing text in a PDF document

To enable text editing, set the interaction mode to PSPDFKit.InteractionMode.CONTENT_EDITOR, like so:

PSPDFKit.load({
        // Use the assets directory URL as a base URL. PSPDFKit will download its library assets from here.
        baseUrl: location.protocol + "//" + location.host + "/assets/",
        document: "/assets/Document.pdf",
        container: "#pspdfkit-container",
    }).then(instance => {
+           instance.setViewState((v) =>
+               v.set("interactionMode", PSPDFKit.InteractionMode.CONTENT_EDITOR)
+           );
        (window as any).instance = instance;
    });

Start the app and open it in your default browser to edit the document’s text:

npm start --open
yarn start --open

Page manipulation

This next section will cover different ways of manipulating pages in PDFs.

Rotating PDF pages

To rotate a page, define the operations object like so:

  • type — The type of operation you want to perform.

  • pageIndexes — Targets the page(s) you want to rotate.

  • rotateBy — Specifies the angle to which the page is to be rotated.

Information

Only multiples of 90 under 360 are allowed as values.

{
    type: "rotatePages",
    pageIndexes: [0], // Rotate page 0.
    rotateBy: 90 // Rotate page 90 degrees clockwise.
}

Supply the operations object above to the PSPDFKit.Instance.applyOperations method:

PSPDFKit.load({
        // Use the assets directory URL as a base URL. PSPDFKit will download its library assets from here.
        baseUrl: location.protocol + "//" + location.host + "/assets/",
        document: "/assets/Document.pdf",
        container: "#pspdfkit-container",
    }).then(instance => {
+           instance.applyOperations([
+            {
+                type: "rotatePages",
+                pageIndexes: [0], // Rotate page 0.
+                rotateBy: 90 // Rotate page 90 degrees clockwise.
+            }
+        ]);
        (window as any).instance = instance;
    });

Cropping PDFs

You can crop a page or pages using the following operations object definition:

  • type — The type of operation you want to perform.

  • pageIndexes — Targets the page(s) you want to crop.

  • cropBox — Accepts the crop window definition as a rect.

{
    type: "cropPages",
    pageIndexes: [1, 2],
    cropBox: new PSPDFKit.Geometry.Rect({
        left: 10,
        top: 10,
        width: 100,
        height: 100
    })
}

Pass the operations object above to the PSPDFKit.Instance.applyOperations method:

PSPDFKit.load({
        // Use the assets directory URL as a base URL. PSPDFKit will download its library assets from here.
        baseUrl: location.protocol + "//" + location.host + "/assets/",
        document: "/assets/Document.pdf",
        container: "#pspdfkit-container",
+    }).then(async instance => {
+           await instance.applyOperations([
+			  {
+				type: "cropPages",
+				pageIndexes: [1, 2],
+				cropBox: new PSPDFKit.Geometry.Rect({
+				  left: 10,
+				  top: 10,
+				  width: 100,
+				  height: 100
+				})
+			  }
+			]);
        (window as any).instance = instance;
    });
Information

If you omit the pageIndexes property from the code above, all the PDF document’s pages will be cropped.

Moving a page within a document

Move a page using the following operations object definition:

  • type — The type of operation you want to perform.

  • pageIndexes — Targets the page(s) you want to move.

  • beforePageIndex — Moves the targeted page(s) before the page specified here.

  • afterPageIndex — Moves the targeted page(s) after the page specified here.

{
    type: "movePages",
    pageIndexes: [0, 4], // Move pages 0 and 4.
    afterPageIndex: 3 // The specified pages will be moved after page 3.
}

Supply this object to the PSPDFKit.Instance.applyOperations method:

await instance.applyOperations([
	{
		type: 'movePages',
		pageIndexes: [0, 4], // Move pages 0 and 4.
		afterPageIndex: 3, // The specified pages will be moved after page 3.
	},
]);

Copying a page

To copy a page/pages, define the operations object like so:

  • type — The type of operation you want to perform.

  • pageIndexes — Targets the page(s) you want to duplicate and inserts each duplicate after the original page.

{
    type: "duplicatePages",
    pageIndexes: [0, 4] // Duplicate pages 0 and 4, and insert each duplicate after the original page.
}

Pass the operations object above to the PSPDFKit.Instance.applyOperations method:

instance.applyOperations([
	{
		type: 'duplicatePages',
		pageIndexes: [0, 4], // Duplicate pages 0 and 4, and insert each duplicate after the original page.
	},
]);

Removing pages from a PDF

You can remove pages from a PDF using the following operations object definition:

  • type — The type of operation you want to perform. The keepPages type keeps the pages specified using pageIndexes. The opposite can be achieved with the removePages type.

  • pageIndexes — Targets the page(s) you want to remove or keep.

{
    type: "removePages",
    pageIndexes: [0, 1, 2] // Remove pages 0, 1, and 2.
}

Pass the operations object above to the PSPDFKit.Instance.applyOperations method:

instance.applyOperations([
	{
		type: 'removePages',
		pageIndexes: [0, 1, 2], // Remove pages 0, 1, and 2.
	},
]);

Adding a page to a PDF document

To add a page to a document, define the operations object like so:

  • type — The type of operation you want to perform.

  • afterPageIndex — The new page is added after the index specified here.

  • backgroundColor — Applies a background color to the new page.

  • pageWidth — Width of the new page.

  • pageHeight — Height of the new page.

  • rotateBy — Rotation for the new page.

{
    type: "addPage",
    afterPageIndex: 1, // Add a new page after page 1.
    backgroundColor: new PSPDFKit.Color({ r: 100, g: 200, b: 255 }), // Set the new page background color.
    pageWidth: 750,
    pageHeight: 1000,
    rotateBy: 0 // No rotation.
}

Now, add a page to the document:

instance.applyOperations([
	{
		type: 'addPage',
		afterPageIndex: 1, // Add a new page after page 1.
		backgroundColor: new PSPDFKit.Color({ r: 100, g: 200, b: 255 }), // Set the new page background color.
		pageWidth: 750,
		pageHeight: 1000,
		rotateBy: 0, // No rotation.
	},
]);

Adding images to a PDF document

You can add images to your document using the image annotation API.

First, convert the image you want to use into a Blob:

const request = await fetch('https://picsum.photos/200');
const blob = await request.blob();

Now, use the instance#createAttachment method to convert it into an attachment that stores the image inside your PDF:

const imageAttachmentId = await instance.createAttachment(blob);

To display this image attachment in the PDF itself, create an image annotation with a MIME type, attachment, description, and bounding box.

Finally, call the create method so that the SDK updates with this new annotation. Putting everything together, you get:

PSPDFKit.load({
        // Use the assets directory URL as a base URL. PSPDFKit will download its library assets from here.
        baseUrl: location.protocol + "//" + location.host + "/assets/",
        document: "/assets/Document.pdf",
        container: "#pspdfkit-container",
+   }).then(async (instance) => {
+       const request = await fetch("https://picsum.photos/200")
+       const blob = await request.blob()
+       const imageAttachmentId = await instance.createAttachment(blob)
+       const annotation = new PSPDFKit.Annotations.ImageAnnotation({
+         pageIndex: 0,
+         contentType: "image/jpeg",
+         imageAttachmentId,
+         description: "Example Image Annotation",
+         boundingBox: new PSPDFKit.Geometry.Rect({
+           left: 10,
+           top: 20,
+           width: 200,
+           height: 200,
+         }),
+       })
+       instance.create(annotation)
+     })
+   }
+ }

Editing page labels in a PDF

To edit a page label, define the operations object like so:

  • type — The type of operation you want to perform.

  • pageIndexes — Targets the page(s) for label editing.

  • pageLabel — Defines the label.

{
    type: "setPageLabel",
    pageIndexes: [0],
    pageLabel: "New page label"
}

Edit the label:

instance.applyOperations([
	{
		type: 'setPageLabel',
		pageIndexes: [0],
		pageLabel: 'New page label',
	},
]);

Splitting a PDF document

To split a document into two PDFs:

  • For each new document, load the original document in headless mode.

  • Remove the pages you don’t want for each document.

  • Export the resulting documents.

In this example, you’ll split a five-page document into two separate documents: one containing the first two pages, and the other containing the last three pages.

You’ll utilize the exportPDFWithOperations(operations) method to apply operations on the current document, which isn’t modified. This method returns an ArrayBuffer that can be used to download the PDF.

Information

If multiple operations are provided, each operation is performed on the resulting document from the previous operation.

Replace the contents of your app.component.ts file located at the src/app/ directory with the following:

import { Component } from '@angular/core';
import PSPDFKit from 'pspdfkit';

@Component({
	selector: 'app-root',
	templateUrl: './app.component.html',
	styleUrls: ['app.component.css'],
	standalone: true,
})
export class AppComponent {
	title = 'PSPDFKit for Web Angular Example';

	ngAfterViewInit() {
		PSPDFKit.load({
			baseUrl: location.protocol + '//' + location.host + '/assets/',
			document: '/assets/document.pdf',
			container: '#pspdfkit-container',
			headless: true,
		}).then((instance) => {
			instance
				.exportPDFWithOperations([
					{
						type: 'removePages',
						pageIndexes: [2, 3, 4],
					},
				])
				.then(function (buffer) {
					const supportsDownloadAttribute = HTMLAnchorElement.prototype.hasOwnProperty(
						'download',
					);
					const blob = new Blob([buffer], {
						type: 'application/pdf',
					});
					if ((navigator as any).msSaveOrOpenBlob) {
						(navigator as any).msSaveOrOpenBlob(
							blob,
							'download.pdf',
						);
					} else if (!supportsDownloadAttribute) {
						const reader = new FileReader();
						reader.onloadend = function () {
							const dataUrl = reader.result;
							downloadPdf(dataUrl);
						};
						reader.readAsDataURL(blob);
					} else {
						const objectUrl = window.URL.createObjectURL(blob);
						downloadPdf(objectUrl);
						window.URL.revokeObjectURL(objectUrl);
					}
				});
		});

		PSPDFKit.load({
			baseUrl: location.protocol + '//' + location.host + '/assets/',
			document: '/assets/example.pdf', // Replace with your document.
			container: '#pspdfkit-container',
			headless: true,
		}).then((instance) => {
			instance
				.exportPDFWithOperations([
					{
						type: 'removePages',
						pageIndexes: [0, 1],
					},
				])
				.then(function (buffer) {
					const supportsDownloadAttribute = HTMLAnchorElement.prototype.hasOwnProperty(
						'download',
					);
					const blob = new Blob([buffer], {
						type: 'application/pdf',
					});
					if ((navigator as any).msSaveOrOpenBlob) {
						(navigator as any).msSaveOrOpenBlob(
							blob,
							'download.pdf',
						);
					} else if (!supportsDownloadAttribute) {
						const reader = new FileReader();
						reader.onloadend = function () {
							const dataUrl = reader.result;
							downloadPdf(dataUrl);
						};
						reader.readAsDataURL(blob);
					} else {
						const objectUrl = window.URL.createObjectURL(blob);
						downloadPdf(objectUrl);
						window.URL.revokeObjectURL(objectUrl);
					}
				});
		});

		function downloadPdf(blob: any) {
			const a = document.createElement('a');
			a.href = blob;
			a.style.display = 'none';
			a.download = 'download.pdf';
			a.setAttribute('download', 'download.pdf');
			document.body.appendChild(a);
			a.click();
			document.body.removeChild(a);
		}
	}
}

Make sure to name the example PDF example.pdf and place it in the src/assets directory.

Start the app and open it in your default browser to split the document and download the resulting PDFs:

npm start --open
yarn start --open

Conclusion

In this post, you learned how to edit a PDF in Angular using Nutrient’s Angular PDF library. If you hit any snags, don’t hesitate to reach out to our Support team for help.

At Nutrient, we offer a commercial, feature-rich, and completely customizable web PDF library that’s easy to integrate and comes with well-documented APIs to handle advanced use cases. Try it for free, or visit our demo to see it in action.

FAQ

Here are a few frequently asked questions about editing PDFs with Angular.

How do I install the Angular PDF library?

You can install the Angular PDF library by following the setup guide in the documentation.

What features does the Angular PDF library offer?

The library offers 30+ features, including text editing, annotations, and page manipulation.

Can I edit PDF text directly in the browser?

Yes, the Angular PDF library allows direct PDF text editing through its content editor mode.

How do I rotate a page in a PDF?

You can rotate a page by using the rotatePages operation and specifying the degree of rotation.

Is the Angular PDF library mobile-friendly?

Yes, the Angular PDF library works on both desktop and mobile devices in modern browsers.

Explore related topics

Share post
Free trial Ready to get started?
Free trial