Reuse Document Editor Instances by Dynamically Moving them in the DOM
Reusing the document editor by moving it in the DOM is a very fast and efficient way to edit documents or snippets in multiple places on a page. This technique and the logic behind it are explained in this article.

Reusing instances of the Document Editor reduces load and initialization time and significantly improves the user experience when editing smaller snippets of text on a page. Once loaded, the Document Editor can be easily reused by moving it in the DOM and dynamically loading the document.
The following screen capture shows three instances of the Document Editor that are being moved around in the DOM in order to edit different documents.
HTML Containers
In the HTML there is a mainContainer, which contains the document editor that has been initialized. The other DIV elements with the editorContainer class name will contain these instances when they are enabled.
<div id="mainContainer">
@Html.TXTextControl().TextControl(settings => {
settings.Dock = DockStyle.Fill;
}).Render()
</div>
<div class="row mb-3">
<div class="col-12">
<label for="container1" class="form-label">Document Editor 1</label>
<div id="container1" class="editorContainer inactive">
</div>
</div>
</div>
<div class="row mb-3">
<div class="col-12">
<label for="container2" class="form-label">Document Editor 2</label>
<div id="container2" class="editorContainer inactive">
</div>
</div>
</div>
<div class="row mb-3">
<div class="col-12">
<label for="container3" class="form-label">Document Editor 3</label>
<div id="container3" class="editorContainer inactive">
</div>
</div>
</div>
JavaScript: ContainerManager
The ContainerManager class handles the DOM manipulation when a new container is activated. All DIV elements with the class name editorContainer will have click events added to them in the constructor.
class ContainerManager {
constructor() {
this.currentContainer = null;
this.storedDocuments = {};
this.attachEventListeners();
}
async enableContainer(container, show) {
if (this.currentContainer !== null) {
await this.saveContainer(this.currentContainer);
this.currentContainer.classList.add("inactive");
}
container.classList.remove("inactive");
container.innerHTML = "";
container.appendChild(document.getElementById("mainContainer"));
await this.replaceContainer(this.currentContainer);
await this.loadContainer(container);
this.currentContainer = container;
if (show === true) {
document.getElementById("mainContainer").style.display = "inline-block";
document.getElementById("mainContainer").style.height = "100%";
window.dispatchEvent(new Event('resize'));
}
}
async replaceContainer(container) {
return new Promise(resolve => {
if (container === null) {
resolve(false);
} else {
TXTextControl.pages.elementAt(0, page => {
page.getImage(TXTextControl.ImageFormat.Png, 100, 7, function (image) {
const img = document.createElement("img");
img.src = "data:image/png;base64," + image;
img.className = "img-thumbnail";
container.innerHTML = "";
container.appendChild(img);
resolve(true);
});
});
}
});
}
async saveContainer(container) {
return new Promise(resolve => {
if (container === null) {
resolve(false);
} else {
var docs = this.storedDocuments;
TXTextControl.saveDocument(TXTextControl.StreamType.InternalUnicodeFormat, function (data) {
docs[container.id] = data;
resolve(true);
});
}
});
}
async loadContainer(container) {
return new Promise(resolve => {
if (container === null) {
resolve(false);
} else {
console.log(this.storedDocuments[container.id]);
if (this.storedDocuments[container.id] !== undefined) {
TXTextControl.loadDocument(TXTextControl.StreamType.InternalUnicodeFormat, this.storedDocuments[container.id].data, function () {
resolve(true);
});
} else {
TXTextControl.resetContents();
resolve(false);
}
}
});
}
attachEventListeners() {
const elements = document.getElementsByClassName("editorContainer");
for (let i = 0; i < elements.length; i++) {
elements[i].addEventListener("click", (elem) => {
if (elem.target !== this.currentContainer && elem.target.className.includes("editorContainer")) {
this.enableContainer(elem.target, true);
}
});
}
}
}
const containerManager = new ContainerManager();
When a container is clicked, an image of the first page of the document is created using the get
Finally, the stored document is loaded into the moved document editor to display the document of that container.
ASP.NET
Integrate document processing into your applications to create documents such as PDFs and MS Word documents, including client-side document editing, viewing, and electronic signatures.
- Angular
- Blazor
- React
- JavaScript
- ASP.NET MVC, ASP.NET Core, and WebForms
Related Posts
Reuse Angular Document Editor Instances in Bootstrap Tabs
The initialization time of document editor instances is time-consuming and requires resources on both the server side and the client side. To reuse instances, they can be moved within the DOM.…
Add JavaScript to PDFs with TX Text Control in C# .NET: Time-Based Alerts…
In this article, we explore how to enrich PDF documents with JavaScript using TX Text Control in C# .NET. Read on to learn how to create time-based alerts that trigger actions based on specific…
Using the Document Editor in SPA Applications using the removeFromDom Method
This article shows how to use the removeFromDom method to remove the Document Editor from the DOM when it is no longer needed. This is useful when the Document Editor is used in a Single Page…
Observe When the Reporting Preview Tab is Active Using MutationObserver
This article shows how to observe when the Reporting Preview tab is active using MutationObserver. The Reporting Preview tab is a feature of the TX Text Control Document Editor that allows you to…
ASP.NETJavaScriptDocument Editor
Removing Empty Pages in TX Text Control with JavaScript
TX Text Control offers a C# solution for removing empty pages already. However, implementing this in JavaScript provides more flexibility for web environments. By using JavaScript methods to…