Flatten PDF form fields in Angular
24 Jul 20266 minutes to read
Overview
Flattening PDF forms converts interactive fields such as textboxes, dropdowns, checkboxes, signatures, etc., into non‑editable page content. Use this when you want to protect filled data, finalize a document, or prepare it for secure sharing.
Prerequisites
- EJ2 Angular PDF Viewer installed and configured
- Basic viewer setup completed with toolbar and page organizer services injected. For more information, see getting started guide
Flatten forms before downloading PDF
- Add a ViewChild to the
PdfViewerComponentso you can access viewer APIs from event handlers. - Intercept the download flow using
downloadStartand cancel the default flow. - Retrieve the viewer’s blob via
saveAsBlob()and convert the blob to base64. - Use
PdfDocumentfrom Syncfusion PDF Library to open the document, setfield.flatten = truefor each form field, then save. - To flatten the form fields when downloading through the Save As option in Page Organizer, repeat steps 2–4 by using
pageOrganizerSaveAsevent.
Complete example
import { Component, ViewChild } from '@angular/core';
import {
PdfViewerComponent, Toolbar, Magnification, Navigation, Annotation, LinkAnnotation,
ThumbnailView, BookmarkView, TextSelection, TextSearch, FormFields, FormDesigner,
PageOrganizer, Print, PageOrganizerSaveAsEventArgs, DownloadStartEventArgs
} from '@syncfusion/ej2-angular-pdfviewer';
import { PdfDocument, PdfField } from '@syncfusion/ej2-pdf';
@Component({
selector: 'app-root',
standalone: true,
imports: [PdfViewerComponent, Toolbar, Magnification, Navigation, Annotation, LinkAnnotation,
ThumbnailView, BookmarkView, TextSelection, TextSearch, FormFields, FormDesigner, PageOrganizer, Print],
template: `
<div style="height: 640px">
<ejs-pdfviewer
#pdfViewer
[documentPath]="'https://cdn.syncfusion.com/content/pdf/form-filling-document.pdf'"
[resourceUrl]="'https://cdn.syncfusion.com/ej2/32.2.5/dist/ej2-pdfviewer-lib'"
(downloadStart)="onDownloadStart($event)"
(pageOrganizerSaveAs)="onPageOrganizerSaveAs($event)"
>
</ejs-pdfviewer>
</div>
`
})
export class AppComponent {
@ViewChild('pdfViewer')
public pdfViewer!: PdfViewerComponent;
blobToBase64(blob: Blob): Promise<string> {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onerror = () => reject(reader.error);
reader.onload = () => {
const dataUrl: string = reader.result as string;
const data: string = dataUrl.split(',')[1];
resolve(data);
};
reader.readAsDataURL(blob);
});
}
flattenFormFields(data: string) {
const document: PdfDocument = new PdfDocument(data);
for (let index = 0; index < document.form.count; index++) {
const field: PdfField = document.form.fieldAt(index);
field.flatten = true;
}
// If both annotations and form fields needs to be flattened, use
// document.flatten = true
document.save(`${this.pdfViewer.fileName}.pdf`);
document.destroy();
}
async handleFlattening(): Promise<void> {
const blob: Blob = await this.pdfViewer.saveAsBlob();
const data: string = await this.blobToBase64(blob);
this.flattenFormFields(data);
}
onDownloadStart(args: DownloadStartEventArgs): void {
args.cancel = true;
this.handleFlattening();
}
onPageOrganizerSaveAs(args: PageOrganizerSaveAsEventArgs): void {
args.cancel = true;
this.handleFlattening();
}
}Expected result
- The downloaded or “Save As” PDF will contain the visible appearance of filled form fields as static, non-editable content.
- Form fields will no longer be interactive or editable in common PDF readers.
Troubleshooting
- If pdfViewer is null, ensure
#pdfVieweris present and the component has mounted before invokingsaveAsBlob(). - Missing
resourceUrl: If viewer resources are not reachable, setresourceUrlto the correct CDN or local path for the ej2-pdfviewer-lib.