MS word Javascript API - event handler for word document/content controls

636 Views Asked by At

Is there a way to call a function when user click on a contentControl or highlighted text in Office-js?

I am working on add-in for MS word, and I have inserted content controls which will be linked with a list in my add-in panel. When I click on list item from add-in, I am able to highlight the text in word document and also able to focus on it.

Now, I want to do the other way around, when I click the highlighted text in word document, a click event should be triggered, and list should be scrolled to the corresponding list item from add-in and highlight it.

I have tried some solutions from this post: MS Word JavaScript API - event handler for Content Controls

I am using typescript and react in add-in development.

2

There are 2 best solutions below

2
On

You may be interested in the onSelectionChanged event which is fired when selection within the content control is changed. Note, this event is provided as in preview and not availble in a production environment yet.

There are no other events for that. You can post or vote for an existing feature request on Tech Community where they are considered when the Office dev team goes through the planning process.

0
On

The onSelectionChanged is pretty slow at firing. I found the onSelectionChange to take ~0.5-2 seconds to fire. This proved to be too slow for my use case, so I wrote a routine to ping the document every 250ms to see if the selection has changed. It is not ideal, but it does work. Best of all it should work outside of the preview only version of the API. The only downside is you are pinging the document every 250ms. If you are doing other actions to the document I highly recommend you pause the await context.sync() action in this code until you complete your other actions. Otherwise this code will slow down your other actions.

Please note that I wrote these functions originally in Vue, and converted it to javascript just now. So there might be a small mistake I made in the conversion process.

The first step is to use setInterval to run the function every 250ms:

    async function subscribeToAllEvents() {
      await Word.run(async (context) => {
        var events = setInterval(
          documentSelectionChangedEventCustom,
          250,
        );
      });
    }

The Function will assume that the user has a content control selected. If they don't then an error will be thrown and caught.

    async function documentSelectionChangedEventCustom() {
      await Word.run(async (context) => {
        // Assumes selection is a content control:
        try {
          let document = context.document;
          let selection = document.getSelection();

          const contentControl = selection.parentContentControl;

          contentControl.load('text');
          contentControl.load('tag');

          await context.sync();
          // Error is thrown above if the user doesn't have a content control selected

          // User has a Content Control Selected:
          const contentControlText = contentControl.text;
          const contentControlTag = contentControl.tag;
          await context.sync();

          // If the user does not have a content control selected then the catch will run. 
         // A better way to do this is to only catch the specific error associated with accessing the content control.
        } catch {
          // User Selection is in the Document
        }
      });
    }