Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
This article introduces key concepts for working with events in Word using the JavaScript API. It contains code samples for registering, handling, and removing event handlers, along with explanations of event life cycles and coauthoring scenarios. Explore the event tables to discover which triggers and objects are supported.
Events in Word
When certain changes occur in a Word document, event notifications fire. The Word JavaScript APIs let you register event handlers that allow your add-in to automatically run designated functions when those changes occur. The following events are currently supported.
| Event | Description | Supported objects | Triggered during coauthoring? |
|---|---|---|---|
onAnnotationClicked |
Occurs when the user selects an annotation. Event data object: AnnotationClickedEventArgs |
Document | No |
onAnnotationHovered |
Occurs when the user hovers the cursor over an annotation. Event data object: AnnotationHoveredEventArgs |
Document | No |
onAnnotationInserted |
Occurs when the user adds one or more annotations. Event data object: AnnotationInsertedEventArgs |
Document | No |
onAnnotationPopupAction |
Occurs when the user performs an action in an annotation pop-up menu. Event data object: AnnotationPopupActionEventArgs |
Document | No |
onAnnotationRemoved |
Occurs when the user deletes one or more annotations. Event data object: AnnotationRemovedEventArgs |
Document | No |
onContentControlAdded |
Occurs when a content control is added. Run context.sync() in the handler to get the new content control's properties.Event data object: ContentControlAddedEventArgs |
Document | Yes |
onDataChanged |
Occurs when data within the content control are changed. To get the new text, load this content control in the handler. To get the old text, don't load it. Event data object: ContentControlDataChangedEventArgs |
ContentControl | Yes |
onDeleted |
Occurs when the content control is deleted. Don't load this content control in the handler, otherwise you won't be able to get its original properties. Event data object: ContentControlDeletedEventArgs |
ContentControl | Yes |
onEntered |
Occurs when the content control is entered. Event data object: ContentControlEnteredEventArgs |
ContentControl | Yes |
onExited |
Occurs when the content control is exited, for example, when the cursor leaves the content control. Event data object: ContentControlExitedEventArgs |
ContentControl | Yes |
onParagraphAdded |
Occurs when the user adds new paragraphs. Event data object: ParagraphAddedEventArgs |
Document | Yes |
onParagraphChanged |
Occurs when the user changes paragraphs. Event data object: ParagraphChangedEventArgs |
Document | Yes |
onParagraphDeleted |
Occurs when the user deletes paragraphs. Event data object: ParagraphDeletedEventArgs |
Document | Yes |
onSelectionChanged |
Occurs when selection within the content control is changed. Event data object: ContentControlSelectionChangedEventArgs |
ContentControl | Yes |
Events in preview
Note
The following events are currently available only in public preview. To use this feature, you must use the preview version of the Office JavaScript API library from the Office.js content delivery network (CDN). The type definition file for TypeScript compilation and IntelliSense is found at the CDN and DefinitelyTyped. You can install these types with npm install --save-dev @types/office-js-preview.
| Event | Description | Supported objects | Triggered during coauthoring? |
|---|---|---|---|
onCommentAdded |
Occurs when new comments are added. Event data object: CommentEventArgs |
Yes | |
onCommentChanged |
Occurs when a comment or its reply is changed. Event data object: CommentEventArgs |
Yes | |
onCommentDeleted |
Occurs when comments are deleted. Event data object: CommentEventArgs |
Yes | |
onCommentDeselected |
Occurs when a comment is deselected. Event data object: CommentEventArgs |
Yes | |
onCommentSelected |
Occurs when a comment is selected. Event data object: CommentEventArgs |
Yes |
Event triggers
Events within a Word document can be triggered by:
- Interacting with the Word user interface (UI) in a way that changes the document.
- Running Office Add-in (JavaScript) code that changes the document.
- Running VBA add-in (macro) code that changes the document.
- Coauthoring remotely and changing the document by using the Word UI or add-in code. For more information, see Events and coauthoring.
Any change that follows the default behavior of Word triggers the corresponding events in a document.
Life cycle of an event handler
An add-in creates an event handler when it registers the event handler. The event handler is destroyed when the add-in deregisters the event handler or when the add-in is refreshed, reloaded, or closed. Event handlers don't persist as part of the Word file, or across sessions with Word on the web.
Events and coauthoring
With coauthoring, multiple people can work together and edit the same Word document simultaneously. For events that a coauthor can trigger, such as onParagraphChanged, the corresponding Event object contains a source property that indicates whether the current user triggered the event locally (event.source == Local) or the remote coauthor triggered the event (event.source == Remote).
Events that use the following data objects are triggered during coauthoring.
CommentEventArgs(preview)ContentControlAddedEventArgsContentControlDataChangedEventArgsContentControlDeletedEventArgsContentControlEnteredEventArgsContentControlExitedEventArgsContentControlSelectionChangedEventArgsParagraphAddedEventArgsParagraphChangedEventArgsParagraphDeletedEventArgs
Register an event handler
The following code sample registers an event handler for the onParagraphChanged event in the document. The code specifies that when content changes in the document, the handleChange function runs.
await Word.run(async (context) => {
eventContext = context.document.onParagraphChanged.add(handleChange);
await context.sync();
console.log("Event handler successfully registered for onParagraphChanged event in the document.");
}).catch(errorHandlerFunction);
As shown in the previous example, when you register an event handler, you indicate the function that should run when the specified event occurs. You can design that function to perform whatever actions your scenario requires. The following code sample shows an event handler function that simply writes information about the event to the console.
async function handleChange(event) {
await Word.run(async (context) => {
await context.sync();
console.log("Type of event: " + event.type);
console.log("Source of event: " + event.source);
}).catch(errorHandlerFunction);
}
Remove an event handler
The following code sample registers an event handler for the onParagraphChanged event in the document and defines the handleChange function that runs when the event occurs. It also defines the deregisterEventHandler() function that you can call later to remove that event handler. You need the RequestContext used to create the event handler to remove it.
let eventContext;
async function registerEventHandler() {
await Word.run(async (context) => {
eventContext = context.document.onParagraphChanged.add(handleChange);
await context.sync();
console.log("Event handler successfully registered for onParagraphChanged event in the document.");
});
}
async function handleChange(event: Word.ParagraphChangedEventArgs) {
await Word.run(async (context) => {
await context.sync();
console.log(`${event.type} event was detected.`);
});
}
async function deregisterEventHandler() {
// The `RequestContext` used to create the event handler is needed to remove it.
// In this example, `eventContext` is being used to keep track of that context.
await Word.run(eventContext.context, async (context) => {
eventContext.remove();
await context.sync();
eventContext = null;
console.log("Removed event handler that was tracking content changes in paragraphs.");
});
}
Use .track()
Certain event types also require you to call track() on the object you're adding the event to.
- Content control events
onDataChangedonDeletedonEnteredonExitedonSelectionChanged
- Comment events (preview)
onCommentAddedonCommentChangedonCommentDeletedonCommentDeselectedonCommentSelected
Example: Content controls events
The following code sample shows how to register an event handler on each content control. Because you're adding the event to the content controls, track() is called on each content control in the collection.
let eventContexts = [];
await Word.run(async (context) => {
const contentControls: Word.ContentControlCollection = context.document.contentControls;
contentControls.load("items");
await context.sync();
// Register the onDeleted event handler on each content control.
if (contentControls.items.length === 0) {
console.log("There aren't any content controls in this document so can't register event handlers.");
} else {
for (let i = 0; i < contentControls.items.length; i++) {
eventContexts[i] = contentControls.items[i].onDeleted.add(contentControlDeleted);
// Call track() on each content control.
contentControls.items[i].track();
}
await context.sync();
console.log("Added event handlers for when content controls are deleted.");
}
});
Example: Comment events
The following code sample registers all five preview comment event handlers on the document's body and removes them when they're no longer needed. It retains one tracked Word.Body and the registration handles for cleanup. Call registerCommentEventHandlers() to register the handlers, then call deregisterCommentEventHandlers() to remove them.
For these body comment events, call body.track() and then await context.sync() before adding the handlers. This synchronization resolves the body's host-assigned reference ID, which Word on the web uses to route comment events. Keep the second synchronization after adding the handlers to complete registration.
The example prevents duplicate registrations and overlapping registration and removal calls. Cleanup uses the original request context, removes all retained handlers, and untracks the shared body once. Errors are logged to the console. If registration fails, run cleanup before trying to register again.
let commentBody: Word.Body | null = null;
const commentEventHandlers: OfficeExtension.EventHandlerResult<Word.CommentEventArgs>[] = [];
let commentEventsBusy = false;
async function registerCommentEventHandlers() {
if (commentEventsBusy || commentBody !== null) {
console.warn("Wait for the current operation and remove existing comment handlers before registering again.");
return;
}
commentEventsBusy = true;
try {
await Word.run(async (context) => {
const body: Word.Body = context.document.body;
commentBody = body;
body.track();
// Resolve the tracked body's host reference before subscribing.
await context.sync();
commentEventHandlers.push(body.onCommentAdded.add(onEventHandler));
commentEventHandlers.push(body.onCommentChanged.add(onChangedHandler));
commentEventHandlers.push(body.onCommentDeleted.add(onEventHandler));
commentEventHandlers.push(body.onCommentDeselected.add(onEventHandler));
commentEventHandlers.push(body.onCommentSelected.add(onEventHandler));
await context.sync();
console.log("Comment event handlers registered.");
});
} catch (error) {
console.error(error);
} finally {
commentEventsBusy = false;
}
}
async function deregisterCommentEventHandlers() {
if (commentEventsBusy) {
console.warn("Wait for the current comment event operation to finish before removing handlers.");
return;
}
if (commentBody === null) {
console.warn("There are no comment event registrations to remove.");
return;
}
const body: Word.Body = commentBody;
commentEventsBusy = true;
try {
// Passing the tracked body reuses the request context for all five handlers.
await Word.run(body, async (context) => {
for (const handler of commentEventHandlers) {
handler.remove();
}
body.untrack();
await context.sync();
});
commentEventHandlers.length = 0;
commentBody = null;
console.log("Comment event handlers removed and body untracked.");
} catch (error) {
console.error(error);
} finally {
commentEventsBusy = false;
}
}
The callbacks below log the event type, source, and affected comment and reply IDs. The changed-event callback also reports the kind of change. These values are included in the event payload, so logging them doesn't require a Word.run batch or context.sync().
async function onEventHandler(event: Word.CommentEventArgs) {
console.log(`${event.type} event. Source: ${event.source}.`);
if (event.source === Word.EventSource.remote) {
console.log("A coauthor triggered this event.");
}
event.commentDetails.forEach((comment: Word.CommentDetail) => {
console.log("Affected comment:", { id: comment.id, replyIds: comment.replyIds });
});
}
async function onChangedHandler(event: Word.CommentEventArgs) {
console.log(`Comment change: ${event.changeType}.`);
if (event.changeType === Word.CommentChangeType.edited) {
console.log("The comment text was edited.");
}
await onEventHandler(event);
}
For a complete runnable example, try Comment events (preview) in Script Lab. It provides deterministic setup by replacing the document body with a sample paragraph, plus create, edit, and delete actions to trigger the events. To exercise selection and deselection, select a comment in Word's Comments pane, then click elsewhere in the document. The sample requires the preview Office.js library and TypeScript definitions described in Events in preview, and a Word client that supports these preview APIs.
See also
- Word JavaScript object model in Office Add-ins
- These and other examples are available in our Script Lab tool:
Office Add-ins