Adding Comments and Replies in our JavaScript PDF viewer
PSPDFKit provides a user interface (UI) for viewing, adding, and deleting comments in PDF documents. You can use comments to build collaborative workflows where multiple users can discuss specific sections of a document without leaving the viewer.
If you use PSPDFKit for Web Server-Backed, the component is available as of version 2020.1 and only if you’re using PSPDFKit Instant. For more information, see PSPDFKit Instant.
If you use PSPDFKit for Web Standalone, the component is available as of version 2023.3.
The difference between the two implementations is that with PSPDFKit for Web Server-Backed, users collaborate in real time and instantly see each others’ changes to a document. With PSPDFKit for Web Standalone, collaboration is asynchronous, which means that changes to a document made by a user aren’t instantly visible to the other users.
Licensing
Comments require a separate component in your PSPDFKit license. Without this included in your license, your app won’t be able to view, search, or add comments. Please contact our Sales team to add comments to your license.
If you’re a new customer, you can try comments without a license key. If you’re an existing customer, please ask our Sales team for a trial license if you’re interested.
Terminology
Before continuing, it’s helpful to first define some terminology as it relates to comments:
-
root annotation — This is the annotation to which all the comments in a single thread are linked.
-
comment thread — This is a group of comments with the same root annotation.
-
comment — This is a single comment added by any user.
Introduction
All comments are linked to their respective root annotations. The comments with the same root annotation are part of a single comment thread. There can be two types of root annotations:
-
MarkupAnnotation
— You can start a new comment thread by selecting some text and clicking on in the markup annotation inline toolbar. In this case, the markup annotation created will act as a root annotation. -
CommentMarkerAnnotation
— A comment marker annotation is a new annotation that can be added anywhere in a PDF document and used to start comment threads.
Getting Started
By default, we don’t show the comment tool () in the main toolbar. This is because we want you to think about the workflow you want for your users and then decide whether or not you want to add it in the main toolbar. For example, if you want to allow the creation of comments from the main toolbar and disable sticky notes, you can do the following:
const toolbarItems = PSPDFKit.defaultToolbarItems .concat({ type: 'comment' }) // Add comment tool. .filter((item) => item.type !== 'note'); // Remove note tool. PSPDFKit.load({ // ... toolbarItems, });
Note that you’ll have to add the comment tool in the main toolbar if you want to add comments using comment markers.
Adding a Comment
Since there are two types of root annotations, there are two ways you can add comments with the user interface.
From the Main Toolbar
This method involves the creation of CommentMarkerAnnotation
before the creation of comments. To add a comment marker, you first need to click on the comment tool () in the main toolbar and then choose a destination on the page where you want to add your comment marker. Once you click on the destination, you’ll see a comment editor where you can add your first comment and start a new thread.
Using Markup Annotations
If you want to add a comment linked to a text annotation, you can do it using the markup annotation. To do this, create a new markup annotation and click on the comment tool () in the inline toolbar. Afterward, you’ll see a comment editor where you can add your first comment and start the new thread.
Mentioning Users in a Comment
To mention a user in a comment, type @, followed by the user’s name, and select the user from the list.
Setting the List of Mentionable Users
To specify the users who can be mentioned in comments, follow these steps:
-
Create a
MentionableUser
object for each mentionable user with the following string type properties:-
Required:
name
,id
-
Recommended:
description
-
Optional:
displayName
,avatar
-
-
Create a list of the
MentionableUser
objects. -
Pass the list to the
mentionableUsers
configuration property when you load PSPDFKit, or to thesetMentionableUsers
method after loading PSPDFKit.
The example below sets two mentionable users when loading PSPDFKit:
PSPDFKit.load({ // ... Other configuration options. mentionableUsers: [{ name: "Jane Doe", id: "jane_doe", description: "[email protected]" }, { name: "John Doe", id: "john_doe", description: "[email protected]" }] })
The example below changes the list of mentionable users after PSPDFKit has loaded:
instance.setMentionableUsers([{ name: "Jane Doe", id: "jane_doe", description: "[email protected]" }, { name: "John Doe", id: "john_doe", description: "[email protected]" }])
Getting the List of Users Mentioned in a Comment
To get the list of all users mentioned in a comment, call the getMentionedUserIds
method on the comment object:
comment.getMentionedUserIds()
Notifying Mentioned Users
To notify users who are mentioned in a comment, add event listeners to the loaded instance.
One approach is to listen to the changes made by a specific user. To do this, listen to the comments.mention
event and send notifications when the event is triggered. In the example below, the listener is triggered when the user john_doe
adds or removes the someCommentObject
comment. The listener won’t trigger if the changes are made by another user, even if those changes are visible to you:
instance.addEventListener("comments.mention", args: { comment: someCommentObject, modifications: [{ userId: "john_doe", action: "ADDED" | "REMOVED" }] } => void)
Another approach is to listen to all changes to comments irrespective of who made them. Listen to the comments.create
, comments.update
, and comments.delete
events to send notifications when comments are created, updated, or deleted. The example below adds separate event listeners for each of these three cases and determines the users mentioned in the affected comments. If you implement a way to keep track of users mentioned in different comments, you can determine if new user mentions have been added or deleted and send notifications to the affected users. This approach gives you control over the different ways comments can change (creation, update, deletion). The limitation of this approach is that changes by any user will trigger notifications; you cannot specify the users whose changes will trigger notifications. Using this approach, you can’t determine who made the last change to a comment, but you can use the comment.creatorName
property to determine the user who created the comment:
instance.addEventListener("comments.create", createdComments => { const users = createdComments .get(0) .forEach(comment => comment.getMentionedUserIds()) }) instance.addEventListener("comments.update", updatedComments => { const users = updatedComments .get(0) .forEach(comment => comment.getMentionedUserIds()) }) instance.addEventListener("comments.delete", deletedComments => { const users = deletedComments .get(0) .forEach(comment => comment.getMentionedUserIds()) })
Deleting a Comment
You can delete an individual comment by clicking the delete button (). If all the comments of a thread are deleted, the corresponding root annotation is automatically deleted.
Document Engine currently doesn’t expose any APIs for deleting a comment.
Disabling the Comments UI
If your license includes comments but you want to disable letting the user view and add comments, you can set showComments
to false
in ViewState
:
const initialViewState = new PSPDFKit.ViewState({ showComments: false, }); const instance = PSPDFKit.load({ // ... other options initialViewState: initialViewState, });
Comment Permissions
There might be situations where you want to disable the creation or deletion of individual comments based on some condition. To do this, you can define the isEditableComment
function as a configuration option when initializing PSPDFKit. When the return value of the isEditableComment
method is false
for a comment, the comment can no longer be deleted by the user. Similarly, isEditableComment
can be used to determine whether or not a user can reply to existing threads:
PSPDFKit.load({ // ... isEditableComment: (comment) => { return comment.rootId !== rootAnnotationId; }, });
In the above example, all the comments that have a root annotation with an id
other than rootAnnotationId
will be editable.
For every comment thread, isEditableComment
receives a temporary draft comment with pageIndex=null
. The rootId
of this draft comment points to the root annotation of the comment thread. If isEditableComment
returns false
, the user won’t be able to add comments in that comment thread:
PSPDFKit.load({ // ... isEditableComment: (comment) => { return comment.pageIndex !== null; }, });
In the above example, a user can’t add a comment in any comment thread.
In case you want to set the permissions after a PSPDFKit instance has been created, you can use instance.setIsEditableComment
:
PSPDFKit.load(options).then((instance) => {
instance.setIsEditableComment((comment) => {
return comment.rootId !== rootAnnotationId;
});
});
Customizing a Comment Block
You can customize the look of a comment block by using CSS. Please make sure you’re using the public class names starting with PSPDFKit-
, as other class names might change in the future and break your application.
For example, if you want to customize the border-radius
of avatars, you can do that by writing the following CSS:
.PSPDFKit-Comment-Avatar {
border-radius: 6px;
}
You can also show avatars in comment blocks by setting a custom renderer:
PSPDFKit.load({ customRenderers: { CommentAvatar: (comment: Comment) => ({ node: element, append: false, // This should always be `false` in this case. }), }, });
If you want to change the avatar after the instance has been created, you can use setCustomRenderers
.
Responsive UI
The UI adapts to the screen size of your browser. In the case of large screens, comment threads are displayed in a sidebar on the right-hand side of a document and are always visible, while on smaller screens, the threads are only visible after you tap on a root annotation.
Rich Text Comments
Rich text editing is supported in comments. Using the UI, you can select parts of a comment and do the following:
-
Make parts of the comment bold, italic, or underlined.
-
Change the color and the background color of parts of the comment.
-
Add hyperlinks to the comment.