Typically, the document editor and document viewer have different use cases and are used in different views in a web application. In most cases, the editor is embedded in an application for creating templates, editing documents, or reviewing documents in a collaborative process. In these cases, the editor takes up most of the view so that the user can focus on editing the document.

However, there are several applications where the Document Editor and Document Viewer are used in the same view:

  • Document editing: Users can switch between editing and viewing modes.
  • Document review: Users can view the document while reviewing it.
  • Template preview: Users can preview the template while editing it.

If you use the Html helper in Razor as described in the documentation, which is implemented in both the editor and the viewer, you will get an error like this:

ControlsFactory does not contain a definition for 'DocumentViewer' and no accessible extension method 'DocumentViewer' accepting a first argument of type 'ControlsFactory' could be found (are you missing a using directive or an assembly reference?)

The above error can come from TextControl or DocumentViewer, depending on which namespace was added to the using directive.

Creating the Instance

Instead of using the Razor Html helper, you can create an instance in your code to solve this problem. The following code snippet shows how to create an instance of the Document Viewer and Document Editor:

@using TXTextControl.Web.MVC
@Html.TXTextControl().TextControl(settings =>
{
settings.Dock = TXTextControl.Web.DockStyle.Fill;
}).LoadDataFromJson(File.ReadAllText("data.json")).Render()
@{
var settings = new TXTextControl.Web.MVC.DocumentViewer.DocumentViewerSettings();
settings.Dock = TXTextControl.Web.MVC.DocumentViewer.DocumentViewerSettings.DockStyle.Fill;
settings.ShowThumbnailPane = false;
var viewer = new TXTextControl.Web.MVC.DocumentViewer.DocumentViewer(settings);
@viewer.Render()
}
view raw test.cshtml hosted with ❤ by GitHub

As you can see, the Document Editor is added as usual using the Html helper class. The Document Viewer is instantiated in code and the Render method is explicitly called to render the viewer in the view. This allows you to create both components in the same view.

Use Case: Live Preview

One use case for using the Document Editor and Document Viewer in the same view is to provide a live preview of the document as the user types. This can be useful for applications that require real-time feedback on the document as the user edits it.

Consider a scenario where a user creates a mail merge template with merge fields, repeating blocks, and formatting. While the user is editing or typing text, an idle timer runs and waits until the user is idle. If the user does not change any content, the document is saved and merged with the live data server-side and loaded into the Document Viewer for preview.

This allows users to get a better feel for the results of a merge, and to design a template without previewing the document in the editor.

Preview update on idle

Idle Timer

The code for this solution is very simple. A JavaScript idle timer implemented as setTimeout will be aborted on the changed event. When the idle state is reached, the template is saved and sent to the Merge endpoint. The returned merged document is then loaded into the Document Viewer.

TXTextControl.addEventListener("textControlLoaded", e => {
let idleTimeout;
function onIdle() {
mergeTemplate();
}
function resetIdleTimer() {
clearTimeout(idleTimeout);
idleTimeout = setTimeout(onIdle, 2000); // Set idle time to 2 seconds
}
// Attach event listener to TXTextControl's "changed" event
TXTextControl.addEventListener("changed", e => {
resetIdleTimer();
});
// Initialize the idle timer
resetIdleTimer();
});
function mergeTemplate() {
TXTextControl.saveDocument(TXTextControl.StreamType.InternalUnicodeFormat, document => {
// call web api endpoint with ajax
$.ajax({
url: '/mailmerge/merge',
type: 'POST',
contentType: 'application/json',
data: JSON.stringify(document.data),
success: function (data) {
// load the document into the viewer
TXDocumentViewer.loadDocument(data);
}
});
})
}
view raw test.js hosted with ❤ by GitHub

Merge Endpoint

The server-side merge endpoint simply takes the template and uses MailMerge TX Text Control .NET Server for ASP.NET
DocumentServer Namespace
MailMerge Class
The MailMerge class is a .NET component that can be used to effortlessly merge template documents with database content in .NET projects, such as ASP.NET web applications, web services or Windows services.
to merge the JSON data into it to create the preview document that is returned to the client and loaded into the Document Viewer.

[HttpPost]
public string Merge([FromBody] string Template)
{
byte[] template = System.Convert.FromBase64String(Template);
using (TXTextControl.ServerTextControl tx = new TXTextControl.ServerTextControl())
{
tx.Create();
tx.Load(template, TXTextControl.BinaryStreamType.InternalUnicodeFormat);
MailMerge mailMerge = new MailMerge();
mailMerge.TextComponent = tx;
string jsonData = System.IO.File.ReadAllText("data.json");
mailMerge.MergeJsonData(jsonData);
byte[] results;
tx.Save(out results, TXTextControl.BinaryStreamType.InternalUnicodeFormat);
return System.Convert.ToBase64String(results);
}
}
view raw test.cs hosted with ❤ by GitHub

Conclusion

Using the Document Editor and Document Viewer in the same view can be a powerful feature for applications that require real-time feedback on the document as the user edits it. By creating an instance of the Document Viewer in code, you can easily add this feature to your application.

Download the sample project from GitHub and test it on your own. If you have any questions or need further assistance, please contact our support team.