Report an issue

guideComments API

# Comments

The Comments class API was deprecated and will be removed in the next release. Please use the CommentsRepository API.

# CommentsRepository

It stores and manages all the comment thread data as well as publishes most of the comments feature API. It is also responsible for using the comments adapter to communicate with the data source.

CommentsRepository is a context plugin. It can be added to a context or to an editor. Add it to the context configuration if you use context in your integration.

Below is the documentation of the public API that can be used to integrate the comments feature with your application.

/**
 * The currently active comment thread.
 * An annotation with this thread will be marked as active.
 *
 * @readonly
 * @observable
 */
activeCommentThread

/**
 * An adapter object that should communicate with the data source
 * to fetch or save the comments data.
 */
adapter

/**
 * Adds a new comment thread.
 *
 * When a target is provided, the comment balloon will be attached to this target.
 *
 * Use this method to load the comments data during the editor initialization
 * if you do not use the adapter integration.
 *
 * **Note:** This method fires the `addCommentThread` event and the default behavior
 * is added as a normal priority listener. It makes it possible to cancel the method
 * or call some custom code before or after the default behavior is executed.
 *
 * **Note:** The comments adapter will send the data only if `commentThreadData.comments`
 * is not empty and `commentThreadData.isFromAdapter` is set to `false`.
 *
 * See also `CommentsRepository#openNewCommentThread()`.
 *
 * An example of loading a comment thread on editor initialization:
 *
 *      commentsRepository.addCommentThread( {
 *          threadId: 'thread-id',
 *          channelId: 'channel-id',
 *          comments: [
 *              {
 *                  commentId: 'comment-1',      // String
 *                  authorId: 'author-id',       // String
 *                  content: 'First comment',    // String
 *                  createdAt: new Date( ... )   // Date instance
 *              },
 *              // ...
 *          ],
 *          target: () => ...,
 *          // Added through a custom UI, do not call the adapter:
 *          isFromAdapter: true
 *      } );
 *
 * @fires addCommentThread
 * @param {Object} commentThreadData The data of the comment thread to add.
 * @param {String} [data.channelId] The ID of a document or context to which the comment thread is added.
 * @param {String} data.threadId The ID of the added comment thread.
 * @param {Array.<Object>} [data.comments=[]] Comments in the comment thread. See the example above.
 * @param {HTMLElement|utils/rect~Rect|Function} [data.target] The target that the comment
 * balloon should be attached to. If a function is passed, it should return a DOM element or `Rect`.
 * @param {Boolean} [data.isFromAdapter=false] A flag describing whether the added data
 * comes from an adapter (`true`) or is new data (`false`). If set to `true`, the
 * comment data will be added only in the editor and will not be sent to the adapter.
 * @returns {CommentThread} An added comment thread.
 */
addCommentThread( commentThreadData ) {}

/**
 * Gets the comment thread data using the adapter and adds the thread to the editor.
 *
 * @param {Object} data
 * @param {String} data.channelId Channel ID.
 * @param {String} data.threadId Comment thread ID.
 * @returns {Promise.<CommentThread>}
 */
fetchCommentThread( data ) {}

/**
 * Returns a comment thread with the given ID.
 *
 * @param {String} threadId
 * @returns {CommentThread|undefined}
 */
getCommentThread( threadId ) {}

/**
 * Returns a list of comment threads added to the repository.
 *
 * You can provide a set of filtering options to narrow down the results set.
 *
 * @param {Object} [options]
 * @param {String} [options.channelId] Return only comment threads added to a given channel.
 * @param {Boolean} [options.skipNotAttached=false] Skip removed comment threads.
 * @param {Boolean} [options.skipEmpty=false] Skip empty comment threads.
 * @param {Boolean} [options.toJSON=false] Return the data in JSON format.
 * @returns {Array.<CommentThread|Object>}
 */
getCommentThreads( options ) {}

/**
 * Checks if a comment thread with a given ID is added to the repository.
 *
 * @param {String} threadId
 * @returns {Boolean}
 */
hasCommentThread( threadId ) {}

/**
 * Creates a new, empty comment thread.
 *
 * Displays a new comment balloon attached to the target and focuses the comment editor.
 * When the comment data is submitted, the comment thread is added to the editor
 * and sent to the adapter.
 *
 * Use this method to start a new comment thread after a user made an action
 * (clicked a button, etc.).
 *
 * @fires addCommentThread
 * @param {Object} commentThreadData
 * @param {String} [commentThreadData.channelId] The ID of a document or context to
 * which the comment is added.
 * @param {String} [commentThreadData.threadId] The ID of the comment thread.
 * Random id will be generated if it is not set. All thread IDs should be unique.
 * @param {HTMLElement|utils/rect~Rect|Function} commentThreadData.target The target that the comment
 * balloon should be attached to. If a function is passed, it should return a DOM element or `Rect`.
 * @returns {CommentThread|null} The created comment thread or `null` if there was a problem
 * creating the thread (for example, if the comments repository was in read-only mode).
 */
openNewCommentThread( commentThreadData ) {}

/**
 * Marks a comment thread with the given ID as active.
 * When `threadId` is `null`, the currently active comment thread will be deactivated.
 *
 * @param threadId {String|null}
 */
setActiveCommentThread( threadId ) {}

/**
 * Changes the read-only state for comment threads.
 *
 * If `channelId` is set, the new state will be applied only to comment threads created in this channel.
 *
 * @param {Boolean} value The new read-only state.
 * @param {String} [channelId] Channel ID.
 */
switchReadOnly( value, channelId ) {}

To use this API, you need to get the comments repository plugin:

// Get the comments repository:
const commentsRepository = editor.plugins.get( 'CommentsRepository' );

// Create a new, empty comment thread on a DOM form field element:
commentsRepository.openNewCommentThread( { channelId, target: formFieldElement } );

// Get all comment threads:
commentsRepository.getCommentThreads();

// Set the adapter:
commentsRepository.adapter = {
    ...
};

# CommentsRepository events

CommentsRepository fires multiple events. It is possible to extend the comments repository behavior using these events or even cancel them. This allows for a further customization of the comments feature.

/**
 * Fired whenever a comment thread is added to the comments repository.
 *
 * The event name includes `channelId` so it is possible to listen only
 * on changes happening in the specified channel.
 *
 * @param {Object} data
 * @param {String} data.channelId The ID of a document or context that the comment thread is added to.
 * @param {String} data.threadId The ID of the added comment thread.
 * @param {Array.<Object>} data.comments Comments in the comment thread.
 * @param {HTMLElement|utils/rect~Rect|Function} [data.target] The target that the comment
 * balloon should be attached to.
 * @param {Boolean} data.isFromAdapter A flag describing whether the comment thread was added on
 * a remote client (`true`) or a local one (`false`).
 */
addCommentThread:channelId

/**
 * Fired whenever a comment thread is removed from the comments repository.
 *
 * The event name includes `channelId` so it is possible to listen only
 * on changes happening in the specified channel.
 *
 * @param {Object} data
 * @param {String} data.channelId The ID of a document or context that the comment thread was removed from.
 * @param {String} data.threadId The ID of the comment thread to remove.
 * @param {Boolean} data.isFromAdapter A flag describing whether the comment thread was removed on
 * a remote client (`true`) or a local one (`false`).
 */
removeCommentThread:channelId

/**
 * Fired whenever a comment is added.
 *
 * The event name includes `channelId` so it is possible to listen only
 * on changes happening in the specified channel.
 *
 * @param {Object} data
 * @param {String} data.channelId The ID of a document or context that the comment thread is added to.
 * @param {String} data.threadId The ID of the comment thread that the comment is added to.
 * @param {String} data.commentId The comment ID.
 * @param {String} data.authorId The comment author ID.
 * @param {String} data.content The comment content.
 * @param {Date} data.createdAt The comment creation date.
 * @param {Boolean} data.isFromAdapter A flag describing whether the comment was added on
 * a remote client (`true`) or a local one (`false`).
 */
addComment:channelId:threadId

/**
 * Fired whenever a comment is updated.
 *
 * The event name includes `channelId` so it is possible to listen only
 * on changes happening in the specified channel.
 *
 * @param {Object} data
 * @param {String} data.channelId The ID of a document or context where the comment was updated.
 * @param {String} data.threadId The ID of the comment thread where the comment was updated.
 * @param {String} data.commentId The comment ID.
 * @param {String} data.content The comment content.
 * @param {Date} [data.createdAt] The comment creation date.
 * @param {Boolean} data.isFromAdapter A flag describing whether the comment was updated on
 * a remote client (`true`) or a local one (`false`).
 */
updateComment:channelId:threadId

/**
 * Fired whenever a comment is removed.
 *
 * The event name includes `channelId` so it is possible to listen only
 * on changes happening in the specified channel.
 *
 * @param {Object} data
 * @param {String} data.channelId The ID of a document or context that the comment is removed from.
 * @param {String} data.threadId The ID of the comment thread that the comment is removed from.
 * @param {String} data.commentId The comment ID.
 * @param {Boolean} data.isFromAdapter A flag describing whether the comment was removed on
 * a remote client (`true`) or a local one (`false`).
 */
removeComment:channelId:threadId

# CommentThread

Represents a comment thread. It stores the comment thread data and the data of all comments in that thread.

/**
 * The channel where the comment thread was created.
 *
 * @readonly
 * @type {String|undefined}
 */
channelId

/**
 * Comments added to the comment thread. A collection of `Comment` instances.
 *
 * @readonly
 * @type {module:utils/collection~Collection}
 */
comments

/**
 * The comment thread ID.
 *
 * @readonly
 * @type {String}
 */
id

/**
 * Whether the comment thread is in read-only state (`true`) or not (`false`).
 *
 * @readonly
 * @observable
 * @member {Boolean} #isReadOnly
 */
isReadOnly

/**
 * Whether the comment thread is attached to any target at the moment.
 *
 * @readonly
 * @type {Boolean}
 */
isAttached

/**
 * The number of comments in a comment thread.
 *
 * @readonly
 * @type {Number}
 */
length

/**
 * Whether the comment thread is in read-only mode.
 * When set to `true`, removing and editing is blocked.
 *
 * @readonly
 * @observable
 * @type {Boolean}
 */
isReadOnly

/**
 * The sum of weights of all comments in this thread. See `Comment#weight`.
 *
 * @readonly
 * @type {Number}
 */
weight

/**
 * Adds a new comment to a comment thread.
 *
 * **Note:** This method fires the `CommentsRepository#event:addComment` event
 * and the default behavior is added as a normal priority listener. It makes it
 * possible to cancel the method or call some custom code before or after the default
 * behavior is executed.
 *
 * @fires CommentsRepository#event:addComment
 * @param {Object} commentData The comment data.
 * @param {String} commentData.commentId The comment ID.
 * @param {String} commentData.authorId The comment author ID.
 * @param {String} commentData.content The comment content.
 * @param {Date} [commentData.createdAt] The comment creation date. If not set, the current
 * date (`new Date()`) will be used.
 * @param {Boolean} [commentData.isFromAdapter=false] A flag describing whether
 * the comment was added from an adapter (`true`) or from the UI (`false`).
 * If set to `true`, the adapter will not be called.
 */
addComment( commentData ) {}

/**
 * Removes a comment thread.
 *
 * **Note:** This method fires the `CommentsRepository#event:removeCommentThread` event
 * and the default behavior is added as a normal priority listener. It makes it
 * possible to cancel the method or call some custom code before or after the default
 * behavior is executed.
 *
 * @fires CommentsRepository#event:removeCommentThread
 * @param {Object} data
 * @param {Boolean} [data.isFromAdapter=false] A flag describing whether the comment thread was
 * removed from an adapter (`true`) or from the UI (`false`). If set to `true`, the adapter
 * will not be called.
 */
remove( data ) {}

/**
 * Creates comment annotations and displays the comment thread attached to the given target.
 *
 * Use only if a comment thread has not been attached yet.
 *
 * @param {HTMLElement|utils/rect~Rect|Function} target A DOM element, `Rect` or
 * a function that returns either of them.
 */
attachTo( target ) {}

# Comment

Represents a single comment.

/**
 * Comment author.
 *
 * @readonly
 * @type {User}
 */
author

/**
 * Comment creation date.
 *
 * @readonly
 * @type {Date}
 */
createdAt

/**
 * Comment content.
 *
 * @readonly
 * @type {String}
 */
content

/**
 * Comment ID.
 *
 * @readonly
 * @type {String}
 */
id

/**
 * The ID of the comment thread that contains this comment.
 *
 * @readonly
 * @type {String}
 */
threadId

/**
 * Whether the comment can be removed.
 * Only the author can remove a comment.
 *
 * @readonly
 * @observable
 * @type {Boolean}
 */
isRemovable

/**
 * Whether the comment can be edited.
 * Only the author can edit a comment.
 *
 * @readonly
 * @observable
 * @type {Boolean}
 */
isEditable

/**
 * Read-only state, inherited from the parent comment thread.
 * When set to `true`, removing and editing is blocked.
 *
 * @readonly
 * @observable
 * @type {Boolean}
 */
isReadOnly

/**
 * The comment weight. It equals the length of the comment content but is never smaller than 200.
 * The weight is used to determine collapsing strategy.
 * This limit is set to avoid a long list of very short collapsed comments.
 *
 * @readonly
 * @type {Number}
 */
weight

/**
 * Removes a comment.
 *
 * **Note:** This method fires the `CommentsRepository#event:removeComment` event
 * and the default behavior is added as a normal priority listener. It makes it
 * possible to cancel the method or call some custom code before or after the default
 * behavior is executed.
 *
 * @fires CommentsRepository#event:removeComment
 * @param {Object} data
 * @param {Boolean} [data.isFromAdapter=false] A flag describing whether the comment was
 * removed from an adapter (`true`) or from the UI (`false`). If set to `true`, the adapter
 * will not be called.
 */
remove( data ) {}

/**
 * Updates a comment.
 *
 * **Note:** This method fires the `CommentsRepository#event:updateComment` event
 * and the default behavior is added as a normal priority listener. It makes it
 * possible to cancel the method or call some custom code before or after the default
 * behavior is executed.
 *
 * @fires CommentsRepository#event:updateComment
 * @param {Object} data The data object.
 * @param {String} [data.content] The comment content.
 * @param {Date} [data.createdAt] The comment creation date.
 * @param {Boolean} [data.isFromAdapter=false] A flag describing whether the comment was
 * updated from an adapter (`true`) or from the UI (`false`). If set to `true`, the adapter
 * will not be called.
 */
update( data ) {}

# Comments adapter

Comments adapter is an object that communicates asynchronously with the data source to fetch or save the comment data. It is used internally by the comments feature whenever a comment is loaded, created or deleted.

The adapter is optional. You might need to provide it if you are using the comments feature without real-time collaboration.

To set the adapter, overwrite the CommentsRepository#adapter property.

/**
 * Called when the editor needs the data for a comment thread.
 *
 * It should return a promise that resolves with the comment thread data.
 * The resolved data object should also have the `isFromAdapter` property set to `true`.
 *
 * @param {String} data.channelId The ID of the document or context to which
 * the comment is added.
 * @param {String} data.threadId The ID of the comment thread that
 * the comment is added to.
 * @returns {Promise}
 */
adapter.getCommentThread( data ) {}

/**
 * Called each time the user removes a comment thread.
 *
 * Keep in mind that comment thread removal happens only
 * for comment threads created outside of the editor.
 * You do not need to implement this method if you use
 * the comments feature inside the editor only.
 *
 * It should return a promise that resolves when the thread is removed.
 *
 * @param {Object} data
 * @param {String} channelId The ID of the document or context that
 * the comment thread is removed from.
 * @param {String} threadId The ID of the thread to remove.
 * @returns {Promise}
 */
adapter.removeCommentThread( data ) {}

/**
 * Called each time the user adds a new comment to a thread.
 *
 * It saves the comment data in the database and returns a promise
 * that should get resolved when the save is completed.
 *
 * If the promise resolves with an object with the `createdAt` property, the
 * comment property will be updated in the comment in the editor.
 * This is to update the comment data with the server-side information.
 *
 * The `data` object does not expect the `authorId` property.
 * For security reasons, the author of the comment should be set
 * on the server side.
 *
 * The `data` object does not expect the `createdAt` property either.
 * You should use the server-side time generator to ensure that all users
 * see the same date.
 *
 * @param {Object} data
 * @param {String} data.channelId The ID of the document or context to which
 * the comment is added.
 * @param {String} data.threadId The ID of the comment thread that
 * the comment is added to.
 * @param {String} data.commentId The comment ID.
 * @param {String} data.content The comment content.
 * @returns {Promise}
 */
adapter.addComment( data ) {}

/**
 * Called each time the user changes the existing comment.
 *
 * It updates the comment data in the database and returns a promise
 * that will be resolved when the update is completed.
 *
 * @param {Object} data
 * @param {String} data.channelId The ID of the document or context where
 * the comment is updated.
 * @param {String} data.threadId The ID of the comment thread where
 * the comment is updated.
 * @param {String} data.commentId The ID of the comment to update.
 * @param {String} data.content The new content of the comment.
 * @returns {Promise}
 */
adapter.updateComment( data ) {}

/**
 * Called each time the user removes a comment from the thread.
 *
 * It removes the comment from the database and returns a promise
 * that will be resolved when the removal is completed.
 *
 * @param {Object} data
 * @param {String} data.channelId The ID of the document or context that
 * the comment is removed from.
 * @param {String} data.threadId The ID of the comment thread that
 * the comment is removed from.
 * @param {String} data.commentId The ID of the comment to remove.
 * @returns {Promise}
 */
adapter.removeComment( data ) {}

# Comments commands

The comments feature adds the addCommentThread command to the editor. It is executed when you click the toolbar button to start a new comment thread. The command is disabled if the selection is collapsed.

editor.execute( 'addCommentThread', { threadId: 'thread-1' } );

// If `threadId` is not specified, `addCommentThread()` will generate a unique ID and use it:
editor.execute( 'addCommentThread' );

You might want to use the addCommentThread command if you provide your own custom UI.

# Annotations

It stores and manages annotation views, i.e. balloons which are shown in the sidebar or inline (or using a custom display mode). Comments and track changes features add annotation views to the annotation plugin, while UI plugins observe the annotations plugin and create the UI basing on the added views.

Using the annotations plugin you can add your own views connected with your custom features. You can also create your own sidebar or another display mode.

Annotations is a context plugin. However, it is required by CommentsRepository, so you do not need to add it to the configuration on your own.

/**
 * Stores all created annotation views. A collection of `AnnotationView`.
 *
 * You can listen to the events fired by this collection to refresh
 * your custom UI (custom sidebar).
 *
 * @readonly
 * @type {module:utils/collection~Collection}
 */
items

/**
 * The currently selected views.
 *
 * Multiple annotation views can be selected at once.
 * For example, the selection can be inside multiple comment markers:
 *
 * <p>
 * 		F<comment-1>oo <comment-2>b{}ar</comment-2> bi</comment-1>z
 * </p>
 *
 * In this situation both `comment-1` and `comment-2` are selected. Different UIs may use this
 * information to show more accurate information. For example, in this case, annotations for
 * both comments should be added to the inline balloon.
 *
 * @observable
 * @member {Array.<module:ui/view~View>} #selectedViews
 */
selectedViews

/**
 * The currently active view.
 * Only one view can be active at a given moment.
 *
 * @observable
 * @member {module:ui/view~View} #activeView
 */
activeView

/**
 * Tracks focus for the annotations plugin.
 *
 * Add a DOM element to this focus tracker to prevent blurring annotations
 * when the DOM element is focused.
 *
 * @type {module:utils/focustracker~FocusTracker}
 */
focusTracker

/**
 * The type of the UI used to display annotation content. Possible values are
 * 'inline' (by default), 'wideSidebar', 'narrowSidebar' or a custom name
 * if a custom UI is used.
 *
 * @readonly
 * @type {String}
 */
uiType

/**
 * Adds a given view to annotations repository.
 * Creates a new annotation view that will wrap the given view.
 *
 * @param {module:ui/view~View} customView The view to add.
 * @param {HTMLElement|module:utils/dom/rect~Rect|Function} target The target that
 * the annotation should be attached to. If a function is passed, it should return
 * a DOM element or `Rect`.
 * @returns {AnnotationView} Annotation view wrapping the given view.
 */
add( customView, target ) {}

/**
 * Removes a given view from annotations together with its wrapping annotation view.
 *
 * @param {module:ui/view~View} customView The view of the item to remove.
 */
remove( customView ) {}

/**
 * Returns an annotation view that wraps the custom view.
 *
 * @param {module:ui/view~View} customView
 * @returns {AnnotationView}
 */
getAnnotationView( customView ) {}

/**
 * Refreshes the order of annotations and fires the `refresh` event.
 *
 * Annotations order is calculated according to the top and left offset
 * of the annotation target.
 */
refresh() {}

/**
 * Registers a custom annotations UI.
 *
 * The UI should be an object that implements the `attach()` and `detach()` methods.
 * These methods are called when the UI is switched to (initialization) and
 * switched from (destruction).
 *
 * @param {String} name The UI name. Used when switching UIs.
 * @param {module:core/plugin~Plugin} plugin The UI instance.
 */
register( name, plugin ) {}

/**
 * Switches the currently used UI.
 *
 * @param {String} name The name of the UI to switch to.
 */
switchTo( name ) {}

# AnnotationView

AnnotationView is a wrapping view for any view added to the Annotations plugin.

/**
 * Informs if an annotation is active.
 *
 * @observable
 * @type {Boolean}
 */
active

/**
 * The view that is wrapped with the annotation view.
 *
 * @readonly
 * @type {module:ui/view~View}
 */
customView

/**
 * Tracks focus on the annotation view.
 *
 * Add a DOM element to this focus tracker to prevent blurring annotation view
 * when the DOM element is focused.
 *
 * @type {module:utils/focustracker~FocusTracker}
 */
focusTracker

/**
 * Informs if there are unsaved changes in the annotation.
 *
 * @observable
 * @type {Boolean}
 */
hasChanges

/**
 * Annotation view height.
 *
 * @observable
 * @type {Number}
 */
height

/**
 * The number of items in the annotation.
 *
 * @observable
 * @member {Number} #length
 */
length

/**
 * The target rectangle that the annotation should be attached to.
 *
 * This is an object with the `top`, `bottom`, `left` and `right` properties.
 * It is used by UIs to properly position the annotation balloon.
 *
 * @observable
 * @type {Object}
 */
targetRect

/**
 * Focuses the annotation view.
 */
focus() {}

To use this API you need to get the annotations plugin:

// Get the annotations repository:
const annotations = editor.plugins.get( 'Annotations' );

// Add a callback fired whenever an active view changes:
annotations.on( 'change:activeView', ( evt, newView, oldView ) => {
    // ...
} );

// Add a view to the annotations:
const annotationView = annotations.add( myView );

# Comment views

Using the comment feature view classes is described in the Annotation customization section.

# BaseCommentThreadView

Available in @ckeditor/ckeditor5-comments/src/comments/ui/view/basecommentthreadview.js.

An abstract comment thread view class that should be used as a base for comment thread view implementations.

It provides some behaviors, flags and building blocks to use when creating a custom comment thread view class.

Extends module:ui/view~View.

/**
 * @param {module:utils/locale~Locale} locale The localization service instance.
 * @param {CommentThread} model The model on which the view will base.
 * @param {User} localUser The current local user.
 * @param {Object} config Additional view configuration.
 * @param {Function} config.CommentView The view class to be used to create comment views.
 * @param {Number} config.maxCommentsWhenCollapsed The number of comments shown when the thread is collapsed.
 * @param {Number} config.maxThreadTotalWeight The maximal weight of a comment thread for which the view will not collapse when not active.
 * @param {Number} config.maxCommentCharsWhenCollapsed The number of characters to which the comment content will be trimmed when
 * the comment thread view is collapsed.
 * @param {Function} config.formatDateTime A function that takes a `Date` object, formats it to a desired string and returns it.
 * It should be used when displaying the comment creation date.
 * @param {module:core/editor/editorconfig~EditorConfig} [config.editorConfig={}] Optional custom configuration for the comment editor.
 * Used for the editor created for adding a new comment and editing an existing comment.
 */
constructor( locale, model, localUser, config ) {}

/**
 * Informs whether the comment thread view is in an active state ("highlighted").
 * A comment thread view is in this state when it is focused or was activated by the user in any different way.
 *
 * @observable
 * @type {Boolean}
 */
isActive

/**
 * Informs whether the comment thread has any changes that have not been saved.
 *
 * @observable
 * @type {Boolean}
 */
isDirty

/**
 * Comment thread model.
 *
 * @protected
 * @readonly
 * @type {CommentThread}
 */
_model

/**
 * Local user.
 *
 * @protected
 * @readonly
 * @type {User}
 *
 */
_localUser

/**
 * The configuration for the whole comment thread view.
 *
 * @protected
 * @readonly
 * @type {Object}
 */
_config

/**
 * The list of comment views. It should be used as a part of the view template.
 *
 * @readonly
 * @type {CommentsListView}
 */
commentsListView

/**
 * The number of comments.
 *
 * @observable
 * @readonly
 * @type {Number}
 */
length

/**
 * Comment input area view. It should be used as a part of the view template.
 *
 * @readonly
 * @type {CommentThreadInputView}
 */
commentThreadInputView

/**
 * Focuses the view.
 */
focus() {}

Events fired by BaseCommentThreadView to communicate with collaboration features:

/**
 * Fired when a user performed an action that should lead to removing the comment thread.
 *
 * This event is not fired by default by any component created by `BaseCommentThreadView`.
 * If you create a view class extending `BaseCommentThreadView`, you should provide
 * a UI element that will fire this event.
 *
 * This event is fired by default when an empty comment thread view (with no comments)
 * loses focus.
 */
removeCommentThread

/**
 * Fired when a user performed an action that should lead to creating a new comment in the comment thread.
 *
 * This event is fired by default when the comment input field of the comment thread is submitted.
 *
 * @param {String} content The content of the new comment.
 */
addComment

Also, all events fired by BaseCommentView are delegated to BaseCommentThreadView. This means that BaseCommentThreadView also can fire these events to communicate with CKEditor 5 collaboration features.

# BaseCommentView

Available in @ckeditor/ckeditor5-comments/src/comments/ui/view/basecommentview.js.

An abstract comment view class that should be used as a base for comment view implementations.

It provides some behaviors, flags and building blocks to use when creating a custom comment view class.

Extends module:ui/view~View.

/**
 * @param {module:utils/locale~Locale} locale The localization service instance.
 * @param {Comment} model The model on which the view will base.
 * @param {Object} config Additional view configuration.
 * @param {Number} config.maxCommentCharsWhenCollapsed The number of characters to which the comment content will be trimmed when
 * the comment thread view is collapsed.
 * @param {Function} config.formatDateTime A function that takes a `Date` object, formats it to a desired string and returns it.
 * It should be used when displaying the comment creation date.
 * @param {module:core/editor/editorconfig~EditorConfig} [config.editorConfig={}] An optional custom configuration for
 * the comment editor. Used by the editor created for adding or editing a comment.
 */
constructor( locale, model, config ) {}

/**
 * Comment model.
 *
 * @protected
 * @readonly
 * @type {Comment}
 */
_model

/**
 * The configuration for the comment view.
 *
 * @protected
 * @readonly
 * @type {Object}
 */
_config

/**
 * Informs whether the comment view is in the editing mode.
 *
 * @observable
 * @readonly
 * @type {Boolean}
 */
isEditMode

/**
 * Informs whether the comment view is expanded.
 *
 * This flag is set by the `expand()` and `collapse()` methods.
 * Comment collapsing is managed by other views.
 *
 * @observable
 * @readonly
 * @type {Boolean}
 */
isCollapsed

/**
 * Stores the currently displayed sub-view.
 *
 * This is a collection that always includes one view: comment content view or comment input view.
 * Depending whether the comment is in editing mode or not, one of the views is in the collection.
 * When the comment mode changes, the content of this collection also changes.
 *
 * By default, the comment is in the "content mode" and this view collection stores the comment content view.
 *
 * @readonly
 * @type {module:ui/viewcollection~ViewCollection}
 */
visibleView

/**
 * Expands the view.
 */
expand() {}

/**
 * Collapses the view.
 */
collapse() {}

/**
 * Focuses the view.
 */
focus() {}

/**
 * Switches the comment to the editing mode.
 *
 * @protected
 */
switchToEditMode() {}

/**
 * Switches the comment back from the editing mode to the content display mode.
 *
 * @protected
 */
switchToDisplayMode() {}

Events fired by BaseCommentView to communicate with CKEditor 5 collaboration features:

/**
 * Fired when a user performed an action that should lead to removing a comment.
 *
 * This event is not fired by default by any component created by `BaseCommentView`.
 * If you create a view class extending `BaseCommentView` you should provide
 * a UI element that will fire this event.
 *
 * @param {String} commentId The ID of the removed comment.
 */
removeComment

/**
 * Fired when a user performed an action that should lead to updating the comment content.
 *
 * This event is fired by default when the comment input field of a comment is submitted.
 *
 * @param {String} commentId The ID of the updated comment.
 * @param {String} commentContent The updated comment content.
 */
updateComment

# CommentThreadView

Available in @ckeditor/ckeditor5-comments/src/comments/ui/view/commentthreadview.js.

The default view for a comment thread.

Extends BaseCommentThreadView.

/**
 * A property used by the template.
 *
 * It works as a visual indicator for a user that an action is about to be performed.
 * The value of this property is used in setting the CSS class.
 * The property is used when the user interacts with the view.
 *
 * @observable
 * @type {String|null}
 */
actionIndicator

/**
 * Returns a template definition that will be passed to `View#setTemplate()`.
 *
 * Overwrite this method if you want to set a custom template for the comment thread view.
 *
 * @protected
 * @returns {module:ui/template~TemplateDefinition} The definition of a comment thread view's template.
 */
_getTemplate() {}

CommentThreadView by default uses the following template. It is returned by CommentThreadView#_getTemplate().

{
    tag: 'div',

    attributes: {
        class: [
            'ck-thread',
            this.bindTemplate.if( 'isActive', 'ck-thread--active' ),
            this.bindTemplate.if( 'isConfirm', 'ck-thread--remove-confirmation' ),
            this.bindTemplate.to( 'actionIndicator', value => value ? `ck-thread--${ value }` : '' )
        ],
        'data-thread-id': this._model.id,
        // Needed for managing focus after adding a new comment.
        tabindex: -1
    },

    children: [
        {
            tag: 'div',
            attributes: {
                class: 'ck-thread__container'
            },
            children: [
                this.commentsListView,
                this.commentThreadInputView
            ]
        }
    ]
}

# CommentView

Available in @ckeditor/ckeditor5-comments/src/comments/ui/view/commentview.js.

The default view for a comment.

Extends BaseCommentView.

/**
 * A property used by the template.
 *
 * It works as a visual indicator for a user that an action is about to be performed.
 * The value of this property is used in setting the CSS class.
 * The property is used when the user interacts with the view.
 *
 * @observable
 * @type {String|null}
 */
actionIndicator

/**
 * Comment editor placeholder value.
 *
 * @observable
 * @type {String}
 */
placeholder

/**
 * Comment creation date.
 *
 * @observable
 * @type {Date}
 */
createdAt

/**
 * Edit button view. Edit button switches the comment to the editing mode.
 *
 * @type {module:ui/button/buttonview~ButtonView}
 */
editButton

/**
 * Remove button view. Remove button shows a confirmation box that fires the `removeComment` event when submitted.
 *
 * @type {module:ui/button/buttonview~ButtonView}
 */
removeButton

/**
 * User view for the comment. Presents the comment author.
 *
 * @type {module:ui/view~View}
 */
userView

/**
 * Returns a template definition that will be passed to `View#setTemplate()`.
 *
 * Overwrite this method if you want to set a custom template for the comment view.
 *
 * @protected
 * @returns {module:ui/template~TemplateDefinition} The definition of a comment thread view's template.
 */
_getTemplate() {}

CommentView by default uses the following template. It is returned by CommentView#_getTemplate().

{
    tag: 'li',

    attributes: {
        class: [
            'ck-comment__wrapper',
            this.bindTemplate.if( 'isConfirm', 'ck-comment--remove-confirmation' )
        ],
        tabindex: -1
    },

    children: [
        {
            tag: 'div',

            attributes: {
                class: [
                    'ck-comment',
                    'ck-annotation',
                    this.bindTemplate.if( 'isEditMode', 'ck-comment--edit' ),
                    this.bindTemplate.to( 'actionIndicator', value => value ? `ck-comment--${ value }` : '' )
                ],
                'data-author-id': this._model.author.id,
                'data-comment-id': this._model.id
            },

            children: [
                this.userView,
                {
                    tag: 'div',

                    attributes: {
                        class: [ 'ck-comment__main', 'ck-annotation__main' ]
                    },

                    children: [
                        {
                            tag: 'div',

                            attributes: {
                                class: [ 'ck-comment__info', 'ck-annotation__info' ]
                            },

                            children: [
                                {
                                    tag: 'span',

                                    children: [
                                        {
                                            text: this.userView.name
                                        }
                                    ],

                                    attributes: {
                                        class: [ 'ck-comment__info-name', 'ck-annotation__info-name' ]
                                    }
                                },
                                {
                                    tag: 'time',

                                    attributes: {
                                        datetime: bind.to( 'createdAt' ),
                                        class: [ 'ck-comment__info-time', 'ck-annotation__info-time' ]
                                    },

                                    children: [
                                        {
                                            text: this.bindTemplate.to( 'createdAt', value => this._config.formatDateTime( value ) )
                                        }
                                    ]
                                }
                            ]
                        },
                        {
                            tag: 'div',

                            attributes: {
                                class: [
                                    'ck-comment__actions',
                                    'ck-annotation__actions'
                                ]
                            },

                            children: [
                                this.editButton,
                                this.removeButton
                            ]
                        },
                        {
                            tag: 'div',

                            attributes: {
                                class: [ 'ck-annotation__content-wrapper' ]
                            },

                            children: this.visibleView
                        }
                    ]
                }

            ]
        }
    ]
}

# Configuration

# Comments

Configuration parameters for the comments feature.

/**
 * The total number of comments shown when the thread view is collapsed.
 *
 * The comments are displayed in the following way:
 *
 * * The first comment is displayed.
 * * An appropriate number of the most recent comments are displayed, based on the configuration.
 * * All other comments are collapsed.
 *
 * For example, when this parameter is set to 3, when collapsed,
 * the thread view will display the first comment and two most recent comments.
 *
 * Defaults to `2`.
 *
 * @type {Number}
 */
maxCommentsWhenCollapsed

/**
 * The maximum number of characters displayed in a comment when the thread view is collapsed.
 * Longer comments will be trimmed.
 *
 * Defaults to `140`.
 *
 * @type {Number}
 */
maxCommentCharsWhenCollapsed

/**
 * The maximal total weight of a thread before the thread becomes collapsed when it is not active:
 *
 * * Thread weight is a sum of the weight of its comments.
 * * Comment weight is equal to the comment length.
 * * The minimal comment weight is 200.
 *
 * Defaults to `500`.
 *
 * @type {Number}
 */
maxThreadTotalWeight

/**
 * Optional configuration for the comments editor.
 *
 * @type {module:core/editor/editorconfig~EditorConfig}
 */
editorConfig

/**
 * View class to be used to create comment thread views
 * (used as annotations - in sidebar balloons or in inline annotations).
 *
 * @type {module:comments/comments/ui/view/basecommentthreadview~BaseCommentThreadView}
 */
CommentThreadView

/**
 * View class to be used to create comment views.
 * It is passed to the comment thread view.
 *
 * @type {module:comments/comments/ui/view/basecommentview~BaseCommentView}
 */
CommentView

Configuration parameters for the sidebar.

/**
 * DOM element into which the sidebar will be inserted.
 *
 * @type {Element}
 */
container

/**
 * Changes how the annotations are positioned inside the sidebar.
 *
 * If set to `true`, the top annotation in the sidebar will never be scrolled
 * above the top edge of the sidebar (which would make it hidden).
 *
 * On the other hand, with this setting enabled, if there is not enough space,
 * annotations will not be positioned exactly next to their linked elements
 * when selected.
 *
 * Defaults to `false`.
 *
 * @type {Boolean}
 */
preventScrollOutOfView

# Example of use

ClassicEditor.create( document.querySelector( '#editor' ), {
    comments: {
        // Show two most recent comments when collapsed.
        maxCommentsWhenCollapsed: 3,
        // Make comments shorter when collapsed.
        maxCommentCharsWhenCollapsed: 100,
        // Allow for up to 3 comments before collapsing.
        maxThreadTotalWeight: 600
    },
    sidebar: {
        container: document.querySelector( '#sidebar' ),
        preventScrollOutOfView: true
    }
} );

Using the CommentThreadView and CommentView properties is described in the Annotation customization section.