Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion Document-Processing-toc.html
Original file line number Diff line number Diff line change
Expand Up @@ -998,6 +998,8 @@
<li><a href="/document-processing/pdf/pdf-viewer/react/annotation/signature-annotation">Handwritten Signature</a></li>
<li><a href="/document-processing/pdf/pdf-viewer/react/annotation/line-angle-constraints">Line Angle Constraint</a></li>
<li><a href="/document-processing/pdf/pdf-viewer/react/annotation/custom-data">Adding custom Data in annotations</a></li>
<li><a href="/document-processing/pdf/pdf-viewer/react/annotation/flatten-annotation">Flatten Annotations into the PDF </a></li>
<li><a href="/document-processing/pdf/pdf-viewer/react/how-to/toggle-annotation-visibility">Show, Hide, or Toggle Annotation Visibility</a></li>
<li>Export and Import Annotations
<ul>
<li><a href="/document-processing/pdf/pdf-viewer/react/annotation/export-import/export-annotation">Export Annotation</a></li>
Expand Down Expand Up @@ -1122,7 +1124,7 @@
<li><a href="/document-processing/pdf/pdf-viewer/react/how-to/get-base64">Retrieve base64-encoded value of a loaded PDF document</a></li>
<li><a href="/document-processing/pdf/pdf-viewer/react/how-to/enable-local-storage">Enable Local Storage</a></li>
<li><a href="/document-processing/pdf/pdf-viewer/react/how-to/add-annotation-in-text-search">Add Rectangle Annotation using Search Text Bounds</a></li>
<li><a href="/document-processing/pdf/pdf-viewer/react/how-to/control-annotation-visibility">Control Annotation Visibility</a></li>
<li><a href="/document-processing/pdf/pdf-viewer/react/how-to/toggle-annotation-visibility">Show, Hide or Toggle Annotation Visibility</a></li>
<li><a href="/document-processing/pdf/pdf-viewer/react/how-to/extract-text-option">Extract Text Option</a></li>
<li><a href="/document-processing/pdf/pdf-viewer/react/how-to/find-text-async">Find Text using findTextAsync</a></li>
<li><a href="/document-processing/pdf/pdf-viewer/react/how-to/extract-text">Extract Text</a></li>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
---
layout: post
title: Flatten Annotations Before Saving the PDF | Syncfusion
description: Learn how all about how to flatten annotations and formfields before saving a PDF in the Syncfusion React PDF Viewer.
platform: document-processing
control: PDF Viewer
documentation: ug
domainurl: ##DomainURL##
---

# Flatten Annotations Before Saving the PDF in React
Flattening annotations permanently merges them into the PDF content. Once flattened:
- Annotations are **no longer editable** in any PDF viewer.
- Useful for **secure sharing**, preventing modifications.
- Ideal when **finalizing markup** before distribution.

## How to Flatten Annotations (React)
Follow these steps to flatten annotations and form fields before saving the PDF.

{% tabs %}
{% highlight js tabtitle="Standalone" %}
{% raw %}
import { createRoot } from 'react-dom/client';
import './index.css';
import * as React from 'react';
import {
PdfViewerComponent,
Toolbar,
Magnification,
Navigation,
LinkAnnotation,
BookmarkView,
ThumbnailView,
Print,
TextSelection,
TextSearch,
Annotation,
FormFields,
FormDesigner,
PageOrganizer,
Inject,
} from '@syncfusion/ej2-react-pdfviewer';
import {
PdfDocument
} from '@syncfusion/ej2-pdf';

function Default() {
let viewer;

const flattenPdf = () => {
viewer.saveAsBlob().then((value) => {
const reader = new FileReader();
reader.onloadend = function () {
const arrayBuffer = reader.result;
const byteArray = new Uint8Array(arrayBuffer);
const document = new PdfDocument(byteArray);
// Flatten all annotations and form fields
document.flatten = true;
document.save('flattened.pdf');
};
reader.readAsArrayBuffer(value);
});
};

return (
<div>
<div className="control-section">
<button onClick={flattenPdf}>Flatten and download PDF</button>

<PdfViewerComponent
ref={(scope) => { viewer = scope; }}
id="container"
documentPath="https://cdn.syncfusion.com/content/pdf/pdf-succinctly.pdf"
resourceUrl="https://cdn.syncfusion.com/ej2/23.2.6/dist/ej2-pdfviewer-lib"
style={{ height: '640px' }}
>
<Inject
services={[
Toolbar,
Magnification,
Navigation,
LinkAnnotation,
BookmarkView,
ThumbnailView,
Print,
TextSelection,
TextSearch,
Annotation,
FormFields,
FormDesigner,
PageOrganizer,
]}
/>
</PdfViewerComponent>
</div>
</div>
);
}
export default Default;

const root = createRoot(document.getElementById('sample'));
root.render(<Default />);
{% endraw %}
{% endhighlight %}
{% endtabs %}

## Notes

- Flattening applies to **all annotation types**: text markup, shapes, stamps, notes, ink, and form fields.
- Once flattened, annotations **cannot be edited or removed**.
- Use flattening **only at export time**, not during regular document interactions.

## See also

- [Annotation Overview](../overview)
- [Annotation Types](../annotation/annotation-types/area-annotation)
- [Annotation Toolbar](../toolbar-customization/annotation-toolbar)
- [Create and Modify Annotation](../annotation/create-modify-annotation)
- [Customize Annotation](../annotation/customize-annotation)
- [Handwritten Signature](../annotation/signature-annotation)
- [Export and Import Annotation](../annotation/export-import/export-annotation)
- [Annotation Permission](../annotation/annotation-permission)
- [Annotation in Mobile View](../annotation/annotations-in-mobile-view)
- [Annotation Events](../annotation/annotation-event)
- [Annotation API](../annotation/annotations-api)
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ The following how-to articles and frequently asked questions for the Syncfusion
* [How to clear all the annotations from the PDF document?](./how-to/clear-annotations)
* [How to configure the annotation selector settings?](./how-to/configure-annotationselector-setting-ts)
* [What are the supported conformance or standards of PDF Viewer?](./how-to/conformance)
* [How to control the visibility of the annotation?](./how-to/control-annotation-visibility-ts)
* [How to Show, Hide or Toggle Annotation Visibility](./how-to/toggle-annotation-visibility)
* [How to convert the PDF library bounds to PDF viewer bounds?](./how-to/convert-pdf-library-bounds-to-pdf-viewer-bounds-ts)
* [How to create PDF Viewer service using ASP.NET Core?](./how-to/create-pdfviewer-service-core)
* [How to create PDF viewer web service using ASP.NET MVC?](./how-to/create-pdfviewer-service)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,233 @@
---
layout: post
title: Show, Hide, or Toggle Annotation Visibility | Syncfusion
description: Learn here all about how to Show, Hide, or Toggle Annotation Visibility and Control annotation visibility in the React PDF Viewer
control: PDF Viewer
platform: document-processing
documentation: ug
domainurl: ##DomainURL##
---

# Show, Hide, or Toggle Annotation Visibility

You can control annotation visibility at two levels in the React PDF Viewer:

- **In the Viewer UI**: Temporarily hide or show annotations to simplify the screen for certain workflows (presentations, reviews) without modifying the source PDF.
- **At export time**: Keep annotations visible inside your app but **hide them only in the downloaded PDF** by setting the `noView` flag.

N> If you’re new to the component, set up the **Standalone** Viewer first using the [Getting Started guide](https://help.syncfusion.com/document-processing/pdf/pdf-viewer/react/getting-started).

## Hide a Specific Annotation

For concise Viewer‑level hiding, remove an annotation by its **id**. If you’ll want to re‑show it later, export annotations to a cache first, then delete the target. See the full, step‑by‑step sample in [Show or hide annotations in React PDF Viewer](./show-hide-annotation)

**Minimal snippet (delete by id):**

{% tabs %}
{% highlight js tabtitle="Standalone" %}
{% raw %}
// Hide (remove) a specific annotation by id
function hideAnnotationById(annotationId) {
const viewer = document.getElementById('container').ej2_instances[0];
viewer.annotationModule.deleteAnnotationById(annotationId);
}

// Example: hide the first annotation currently in the document
function exampleHideFirst() {
const viewer = document.getElementById('container').ej2_instances[0];
if (viewer.annotationCollection?.length) {
hideAnnotationById(viewer.annotationCollection[0].annotationId || viewer.annotationCollection[0].id);
}
}
{% endraw %}
{% endhighlight %}
{% endtabs %}

## Show a Specific Annotation

Re‑import previously exported annotations and (optionally) filter the JSON to reinsert only the one you need. (Export must be done **before** deletion.)

**Minimal snippet (re‑import from cache):**

{% tabs %}
{% highlight js tabtitle="Standalone" %}
{% raw %}
// Assume you cached this earlier via viewer.exportAnnotationsAsObject()
function showFromCache(exportedObjectString) {
const viewer = document.getElementById('container').ej2_instances[0];
if (exportedObjectString) {
viewer.importAnnotation(JSON.parse(exportedObjectString));
}
}
{% endraw %}
{% endhighlight %}
{% endtabs %}

## Hide or Show All Annotations

Use `deleteAnnotations()` to remove **all** annotations, then re-import them from cache to show again.

**Minimal snippet (toggle all using cache):**

{% tabs %}
{% highlight js tabtitle="Standalone" %}
{% raw %}
let __cache = null;
let __areHidden = false;

async function toggleAllAnnotations() {
const viewer = document.getElementById('container').ej2_instances[0];

if (!__areHidden) {
__cache = await viewer.exportAnnotationsAsObject();
viewer.deleteAnnotations();
__areHidden = true;
} else {
if (__cache) viewer.importAnnotation(JSON.parse(__cache));
__areHidden = false;
}
}
{% endraw %}
{% endhighlight %}
{% endtabs %}

## Conditional Visibility (Annotations by Type)

To hide a **type** (e.g., all text markups) while keeping others, export to cache, clear the UI, then **re-import only the allowed types**. The export payload is JSON; filter by each type’s bucket before importing. (Structure may vary by version—adjust keys accordingly.)

{% tabs %}
{% highlight js tabtitle="Standalone" %}
{% raw %}
// Example: hide all Text Markup (Highlight, Underline, Strikethrough, Squiggly)
async function hideTextMarkup() {
const viewer = document.getElementById('container').ej2_instances[0];

const exportObject = await viewer.exportAnnotationsAsObject();
viewer.deleteAnnotations();

const parsed = JSON.parse(exportObject);
const filtered = {
...parsed,
textMarkupAnnotations: [] // Key name depends on version; inspect your export object
};

viewer.importAnnotation(filtered);
}
{% endraw %}
{% endhighlight %}
{% endtabs %}

## Role‑based Visibility Control

Implement role filters on top of the export/delete/import strategy:

- **Admin →** see **all annotations**
- **Editors →** see **all markup**
- **Viewers →** see **only comments or approved stamps**

Use per‑annotation metadata (e.g., `subject`, `author`, `customData`) to include/exclude what each role can view.

{% tabs %}
{% highlight js tabtitle="Standalone" %}
{% raw %}
// Example: 'Viewer' role → only Approved stamps
async function applyViewerRole() {
const viewer = document.getElementById('container').ej2_instances[0];
const exportObject = await viewer.exportAnnotationsAsObject();
const payload = JSON.parse(exportObject);

const roleFiltered = {
...payload,
textMarkupAnnotations: [],
shapeAnnotations: [],
freeTextAnnotations: [],
inkAnnotations: [],
stampAnnotations: (payload.stampAnnotations || []).filter(s =>
s.subject === 'Approved' || s.customData?.status === 'approved'
)
};

viewer.deleteAnnotations();
viewer.importAnnotation(roleFiltered);
}
{% endraw %}
{% endhighlight %}
{% endtabs %}

## Toggle Annotation Visibility (UI Button Example)

For a simple UI toggle (single button), reuse the **toggle all** function above.

## Events Related to Visibility

There aren’t built‑in `annotationShown`/`annotationHidden` events. Use **export/import** life-cycle events to infer visibility changes (e.g., `exportStart`/`exportSuccess` when hiding, and `importStart`/`importSuccess` when showing). For all annotation‑level events (add/remove/select/resize/etc.), see **Annotation Events** (link below).

**Tiny example:**

{% tabs %}
{% highlight js tabtitle="Standalone" %}
{% raw %}
function wireVisibilityEvents() {
const viewer = document.getElementById('container').ej2_instances[0];

viewer.exportStart = () => console.log('annotationHidden:start');
viewer.exportSuccess = () => console.log('annotationHidden:success');

viewer.importStart = () => console.log('annotationShown:start');
viewer.importSuccess = () => console.log('annotationShown:success');
}
{% endraw %}
{% endhighlight %}
{% endtabs %}

## Control annotation visibility only in the exported PDF

If you want annotations **visible in your app** but **hidden in the saved PDF**, set the **`PdfAnnotationFlag.noView`** flag on each annotation before download using the EJ2 PDF library.

{% tabs %}
{% highlight js tabtitle="Standalone" %}
{% raw %}
import { PdfAnnotationFlag, PdfDocument } from '@syncfusion/ej2-pdf';

// Download the current PDF with annotations flagged as `noView`
async function downloadWithNoView() {
const viewer = document.getElementById('container').ej2_instances[0];

const blob = await viewer.saveAsBlob();
const reader = new FileReader();
reader.onload = function () {
const base64 = String(reader.result).split('base64,')[1];
const doc = new PdfDocument(base64);

for (let i = 0; i < doc.pageCount; i++) {
const page = doc.getPage(i);
for (let j = 0; j < page.annotations.count; j++) {
const annot = page.annotations.at(j);
annot.flags |= PdfAnnotationFlag.noView; // hide in exported PDF
}
}

doc.saveAsBlob().then((modified) => {
const linkReader = new FileReader();
linkReader.onload = function () {
const a = document.createElement('a');
a.href = linkReader.result;
a.download = 'without-annotations.pdf';
a.click();
};
linkReader.readAsDataURL(modified.blobData);
});
};
reader.readAsDataURL(blob);
}
{% endraw %}
{% endhighlight %}
{% endtabs %}

[View sample in GitHub](https://github.com/SyncfusionExamples/react-pdf-viewer-examples/tree/master/How%20to)

## See also

- [Annotation Overview](../overview)
- [Show or hide annotations in React PDF Viewer](./show-hide-annotation)
- [Import and export annotations](../annotation/export-import/export-annotation)