Building a mobile e-book or document reader with Angular, Capacitor, and ngx-extended-pdf-viewer can be a great choice, especially when you need PDF rendering, annotation support, and a familiar web-based development workflow. However, developers sometimes run into a frustrating issue on iOS: when trying to add a text annotation inside a PDF, the keyboard may suddenly disappear, and the annotation editor seems to close or get removed.
This problem can be confusing because the application may log an annotation editor event such as FreeTextEditor removed, making it look as if the user deleted the annotation. In reality, the issue is often related to how iOS handles text input sessions inside a WebView rather than to the PDF annotation itself.
This article explains what is happening, why it happens on iOS, how to diagnose it, and what the strongest long-term solution looks like for production apps.
Understanding the Problem
In a typical Angular and Capacitor mobile app, ngx-extended-pdf-viewer is used to display and annotate PDFs. When the user taps to add a free-text annotation, the viewer creates a temporary text editor on top of the PDF page. On desktop browsers this usually works well. On iOS, however, the on-screen keyboard may disappear unexpectedly while the user is trying to type.
At the same time, the application may log something similar to:
annotation editor eventeditorType: FreeTextEditortype: removed
This gives the impression that the annotation was deliberately removed. But the log alone does not tell the full story.
Why the removed Event Is Misleading
The annotationEditorEvent emitted by ngx-extended-pdf-viewer refers to the lifecycle of the editor instance, not only to a true delete action. In other words, a removed event does not always mean that the user deleted a saved annotation. It can also mean that the temporary editor object used during placement or editing was destroyed.
This distinction is very important.
When a new free-text annotation is created, the viewer often generates a temporary editor first. If something interrupts that editing session before it is fully committed, the viewer may tear down the temporary editor and emit a removed event. That is exactly why a removed event can appear even during new annotation placement.
What iOS Logs Reveal
On iOS, additional console messages often appear around the same time, such as input session warnings mentioning invalid or inactive text input sessions. These logs strongly suggest that the real issue is not the PDF annotation logic itself, but a failure in the iOS text-input session inside WKWebView.
This is the likely sequence:
- The user taps to place a free-text annotation.
- The PDF viewer creates a temporary text editor.
- iOS loses the active text-input session.
- The editor is no longer stable in the DOM.
- The viewer removes that temporary editor.
- The app receives a
removedevent.
So the annotation editor is not being intentionally deleted. It is being torn down because the iOS keyboard and input session became unstable.
How to Detect an Interrupted Annotation Instead of a Real Delete
A more reliable way to interpret the event is to inspect the editor object included in the event payload.
In interrupted cases, the event often contains details like:
deleted: falseisAttachedToDOM: falseannotationElementId: null
This combination is a strong signal that the annotation was never fully committed and that the editor was removed before becoming a real saved annotation.
A practical interpretation rule is:
- If the editor type is
FreeTextEditor - and the event type is
removed - and the editor is not attached to the DOM
- and it is not marked as deleted
- and it has no persisted annotation ID
then the editor was most likely interrupted before commit.
This helps separate a real delete action from an iOS input-session failure.
Why a Simple Auto-Reentry Is Only a Workaround
A common first idea is to automatically re-enter free-text mode when this interrupted state is detected. This can reduce friction for the user, but it does not solve the real problem.
The root issue is still the unstable text-entry experience inside the WebView-based PDF editor. If the iOS input session keeps failing, reopening the same editor may simply reproduce the problem.
That is why automatic re-entry should be seen as a temporary usability improvement, not a strong technical fix.
The Strong Solution for Production Apps
The strongest architecture is to stop relying on the built-in PDF free-text editor on iOS for actual text input.
Instead, use this approach:
- Let the user tap the PDF to choose the annotation position.
- Open your own Ionic modal or text-entry interface.
- Let the user type the annotation text in a normal Ionic input or textarea.
- Programmatically create the free-text annotation in the PDF viewer.
- Save and restore annotations through your own persistence layer.
This approach is much more reliable because it avoids the fragile path of typing directly into a contenteditable editor hosted inside the PDF layer in WKWebView.
Recommended Architecture
A solid iOS-friendly PDF annotation design has four parts:
1. Tap-to-Place Coordinate Capture
Instead of entering text directly into the PDF editor, the user first activates an “Add text” mode. When they tap a page, the app captures the page index and relative coordinates of that tap.
These coordinates can be stored in normalized form, such as percentages of page width and height. That makes them easier to persist and reapply later.
2. Ionic Modal for Text Entry
Once the placement point is known, the app opens an Ionic modal. The modal collects:
- annotation text
- font size
- color
- optional metadata if needed
Because the user types into a normal Ionic form element, the iOS keyboard behaves far more reliably than it does inside the PDF free-text editor layer.
3. Programmatic Annotation Insertion
After the user confirms the text, the app creates the annotation programmatically using the viewer’s annotation APIs. The exact payload shape may depend on the installed viewer version, so a good strategy is to inspect a real exported annotation from the current version and use that structure as the template.
This gives full control over annotation creation without depending on the fragile in-viewer typing experience.
4. Save and Export Flow
A robust app should save annotations in two ways:
- a stable, app-defined annotation model
- the viewer’s serialized annotation data
The app-defined model acts as the canonical source of truth. The serialized viewer export is useful for rendering and replaying annotations in the current viewer version. Keeping both makes future upgrades safer.
Why This Architecture Is Better
This design offers several major advantages:
Better iOS Stability
The keyboard is handled by standard Ionic UI rather than by a PDF editor running inside the WebView.
Better User Experience
Users see a predictable input form instead of a disappearing keyboard or a broken inline text box.
Better Long-Term Maintainability
A custom annotation model protects the app from future changes in internal viewer APIs.
Better Cross-Platform Consistency
The same annotation workflow can be used across iOS, Android, and desktop, with iOS simply disabling the fragile built-in free-text editor.
How to Persist Annotations Safely
When saving annotations, it is wise to keep both:
- the serialized annotation data produced by the viewer
- your own custom storage model, including:
- PDF ID
- page index
- normalized X and Y coordinates
- text value
- font size
- color
- timestamps
This gives the app a reliable fallback if the viewer’s internal serialization changes in a future release.
A strong production strategy also includes storing the viewer version along with the saved annotations. That way, if a library upgrade later changes annotation import or export behavior, you know which data format was originally used.
Should You Hide the Built-In Free-Text Button on iOS?
Yes. For iOS builds, it is usually best to hide or disable the built-in free-text annotation tool and replace it with a custom “Add text” button. This guides users into the stable flow and avoids the problematic inline editor entirely.
The custom button can trigger the placement-and-modal workflow instead.
Best Practices for Implementation
To make this solution production-ready, follow these best practices:
- detect iOS and use the custom text workflow there
- avoid re-rendering the PDF viewer during annotation interactions
- store coordinates in normalized form
- pin the PDF viewer version used in production
- test save and reload across real devices
- maintain a separate annotation domain model instead of trusting only viewer internals
- use a clean retry flow if annotation insertion fails
Common Mistakes to Avoid
Many annotation bugs become worse when the app:
- changes the PDF source while editing
- destroys and recreates the viewer component
- relies only on the
removedevent without inspecting the editor state - assumes that
removedalways means delete - hardcodes version-sensitive annotation mode values
- tries to “fight” the iOS keyboard problem inside the built-in editor instead of changing the architecture
Avoiding these mistakes will save a lot of debugging time.
Final Thoughts
If your Angular and Capacitor app uses ngx-extended-pdf-viewer and text annotations behave unpredictably on iOS, the issue is most likely not a normal annotation delete. It is usually an interruption in the WebView text-input session that causes the temporary FreeTextEditor to be removed before the annotation is committed.
You can detect this more accurately by checking fields such as deleted, isAttachedToDOM, and annotationElementId. However, the real long-term solution is architectural: do not rely on the built-in free-text typing experience on iOS.
Instead, capture the placement point inside the PDF, open an Ionic modal for text entry, create the annotation programmatically, and store the result through a stable save/export workflow. That approach is far more reliable, easier to maintain, and better suited for real-world mobile apps.
For teams building serious PDF-based e-book readers, study apps, form-fillers, or document annotation tools, this strategy offers the best balance of usability, maintainability, and platform stability.
I can also turn this into a publish-ready version with a title tag, meta description, headings optimized for WordPress, and a comma-separated keyword list.


