Do you have an issue with a specific file(s)?
Can you reproduce using one of our samples or online demos?
Are you using the WebViewer server?
Does the issue only happen on certain browsers?
Is your issue related to a front-end framework?
Is your issue related to annotations?
Please give a brief summary of your issue:
(Think of this as an email subject)
Persist Document Edits across Refreshes(DB Schema Help or Best Practices)
Please describe your issue and provide steps to reproduce it:
(The more descriptive your answer, the faster we are able to help you)
Trying to persist edits across refreshes and offer the functionality to revert the document across edits. I know we use Content Edit Placeholder Annotations to render edits, and currently I store XFDF data on the backend. Is there a different way I should approach storing edits? I tried using content replacer server sidebut its a bit difficult to match the exact styling
Please provide a link to a minimal sample where the issue is reproducible:
Hello, Iām AiRon, an automated tech support bot While you wait for one of our customer support representatives, I can help you with your question.
Persisting document edits across refreshes and enabling document versioning involves handling content edit placeholder annotations and efficiently storing the changes. Using XFDF data is a common approach to store annotations, but for content edits, you might consider additional strategies.
Some things you can try:
Continue using XFDF for annotations, which is effective for saving and loading annotations like highlights, comments, etc.
For content edits, consider using the getDocumentContent and updateDocumentContent APIs to manage text and image changes directly within the document. This allows you to maintain the documentās styling and structure.
Implement a versioning system in your backend to save each state of the document. This can be done by storing the documentās content or the changes applied using a unique identifier for each version.
Utilize the ContentEditManager events, such as add and delete, to track changes and update your stored data accordingly.
Consider using a database to store different versions of the document to facilitate the ārevertā functionality.
To keep track of changes to the document/annotations for the use of saving changes across refreshes, the XFDF approach is recommended, particualrly to take advantage of the exportAnnotationCommand/importAnnotationCommand APIs. Combined with the annotationChanged event, this can help āauto-saveā by sending the XFDF data to your backend whenever changes are made.
Does this account for edits though, Iām using the content edit manager to listen for when editing has completed pull the annotation to export itās XFDF. However this is a placeholder annotationās XFDF
XFDF: <?xml version="1.0" encoding="UTF-8" ?>
I already implemented exporting for other types of annotations and it works well!
Apologies for the confusion. After further investigation, we found that importAnnotationCommand/exportAnnotationCommand is not recommended for tracking changes made using content edit. The document is separate from the annotations, so it will also need to be saved separately in order to persist document edits across refreshes. This is because the content edit boxes are placeholder annotations, and do not accurately capture the actual content changes that occur.
While not using content edit, we recommend using the importAnnotationCommand/exportAnnotationCommand as before. However, while using content edit, we would recommend using getFileData() to capture the document every time a content edit box is added/changed/deleted. Instead of the annotationChanged event, we would recommend the undoRedoStatusChanged on the ContentEdit namespace. An example code snippet would look like this:
async function updateDataBase() {
console.log('editBoxesAvailable');
const doc = await documentViewer.getDocument();
// I would use exportAnnotations while using content edit since we're focusing on changes to the document
const xfdf = await annotationManager.exportAnnotations({
fields: true,
widgets: true,
links: true,
})
const data = await doc.getFileData({
// You can uncomment the line below if you would like to save the document with annotations in it, otherwise save xfdf seperately
// xfdf,
flags: Core.SaveOptions.LINEARIZED,
});
// open the file in a new tab
const arr = new Uint8Array(data);
const blob = new Blob([arr], { type: 'application/pdf' });
// << Save the blob in your database >>
// For demonstration purposes, this will open the blob in a new tab
const url = URL.createObjectURL(blob);
window.open(url, '_blank');
}
// When entering content edit mode, track the changes made to the document
instance.Core.documentViewer.getContentEditManager().addEventListener('contentEditModeStarted', () => {
console.log('contentEditModeStarted');
instance.Core.ContentEdit.addEventListener('undoRedoStatusChanged', updateDataBase);
});
// When exiting content edit mode, stop tracking the changes
instance.Core.documentViewer.getContentEditManager().addEventListener('contentEditModeEnded', () => {
console.log('contentEditModeEnded');
instance.Core.ContentEdit.removeEventListener('undoRedoStatusChanged', updateDataBase);
});
For your convenience, you can find the API docs for the APIs used here: