ONLYOFFICE Docs v7.3 released: enhanced forms, SmartArt, new security settings, Watch Window, and more
ONLYOFFICE Docs v7.3 released

Replacing content in an existing ContentControl with a Plugin

Hello, I’ve been trying to replace the content inside an existing content control using the Plugin API.
Here’s an example:
image
I’d like to replace the content control’s content with the actual employee name.

I have 2 cases I’d like to cover - one where I have to insert content from a remote URL docx document (essentially copying the content from one document into a specific place inside the document, marked using a content control) and another one where I simply replace the text inside.
The 1st case I’ve “hacked” together like

window.Asc.plugin.executeMethod(
    "GetAllContentControls",
    [],
    (returnValue) => {
      returnValue
        .forEach((control) => {
          const id = control.InternalId
          const key = control.Tag.slice(tagPrefix.length)
          const value = values[key]
          if (!value) return
            const cc  = {
              Props: {
                Id: control.Id,
                Lock: 3,
                Tag: control.Tag,
              },
              Url: "http://my-documents.com/document.docx",
            }
            window.Asc.plugin.executeMethod("InsertAndReplaceContentControls", [
              [cc],
            ])
        })

This however doesn’t do what I want - it instead creates a new content control, which is not what I want. I tried passing in an InternalId to the Props like so

            ...
            const cc  = {
              Props: {
                Id: control.Id,
                Lock: 3,
                Tag: control.Tag,
                InternalId: control.InternalId
              },
              Url: "http://my-documents.com/document.docx",
            }
            window.Asc.plugin.executeMethod("InsertAndReplaceContentControls", [
              [cc],
            ])

I thought that it would solve it, but instead I get a cryptic error
image

1st question - What’s the recommended way to replace content controls with content from another document?

The 2nd case uses a similar approach

window.Asc.plugin.executeMethod(
    "GetAllContentControls",
    [],
    (returnValue) => {
      returnValue
        .forEach((control) => {
          const id = control.InternalId
          const key = control.Tag.slice(tagPrefix.length)
          const value = values[key]
          if (!value) return
            window.Asc.plugin.executeMethod(
              "SelectContentControl",
              [id],
              () => {
                window.Asc.plugin.executeMethod("PasteText", [`${value}`])
              }
            )
        })

This approach seems hacky to me because of the selection & pasting – the replacing doesn’t happen atomically and can for example get messy if the editor gets closed.

2nd question - What other ways are available for replacing content control’s content without selecting and pasting text inside them?
3rd question - Can this be achieved using the Asc.plugin.callCommand method & the Document Builder API?
4th question - What are the differences between the Plugin API and the Document Builder API w/ the callCommand method?
5th question - How can I wrap a selection into a content control using Plugin API or the Document Builder API?

Hello @fr3fou
I believe you have to take a look at this plugin example: sdkjs-plugins/example_work_with_content_controls at master · ONLYOFFICE/sdkjs-plugins · GitHub
It contains ‘insert and replace’ feature and it works properly. I hope it will be useful.
As for your questions:

What’s the recommended way to replace content controls with content from another document?

You can use InsertAndReplaceContentControls method as you already did it.

What other ways are available for replacing content control’s content without selecting and pasting text inside them?

You can use the same method: ONLYOFFICE Api Documentation - InsertAndReplaceContentControls
You can specify internalID and change it by this step.

Can this be achieved using the Asc.plugin.callCommand method & the Document Builder API?

There’re no such methods for DocBuilder.

What are the differences between the Plugin API and the Document Builder API w/ the callCommand method?

The purpose of the builder is to create/modify files without the participation of a graphical interface (editor). The purpose of plugins is to extend the current functionality of the editor. There’re literally different features. You can face similar methods on the both sides, but they are not exactly identical.

How can I wrap a selection into a content control using Plugin API or the Document Builder API?

Please take a look at this method: ONLYOFFICE Api Documentation - AddContentControl
Also this example will be useful sdkjs-plugins/example_add_rich_text_content_control at develop · ONLYOFFICE/sdkjs-plugins · GitHub

1 Like

Thank you Alexandre very much for your reply.
Is there a reason the example_add_rich_text_content_control example is on the develop branch on GitHub but not on master yet?

Also regarding this:

You can use the same method: ONLYOFFICE Api Documentation - InsertAndReplaceContentControls
You can specify internalID and change it by this step.

I’d like a way to replace the text inside the ContentControl but also preserve any formatting that has been applied to it (e.g font size / font style (italic, bold, etc), color, etc). The way I’ve achieved that is by using SelectContentControl & PasteText but it feels hacky (as I outlined in the original post). Is there an alternative to way to do that?

Is there a reason the example_add_rich_text_content_control example is on the develop branch on GitHub but not on master yet?

We merge it to master from time to time. Anyway, the mentioned example works.

I’d like a way to replace the text inside the ContentControl but also preserve any formatting that has been applied to it (e.g font size / font style (italic, bold, etc), color, etc). The way I’ve achieved that is by using SelectContentControl & PasteText but it feels hacky (as I outlined in the original post). Is there an alternative to way to do that?

You can try to use internalID to specify content control and change its contents. Please check out this code example: https://github.com/ONLYOFFICE/sdkjs/blob/0ab8241d66b1040bffc4069aec0ca11a8f041010/word/api_plugins.js#L138

* // Add new content control
     * var arrDocuments = [{
     *  "Props": {
     *       "Id": 100,
     *       "Tag": "CC_Tag",
     *       "Lock": 3
     *   },
     *   "Script": "var oParagraph = Api.CreateParagraph();oParagraph.AddText('Hello world!');Api.GetDocument().InsertContent([oParagraph]);"
     *}]
     * window.Asc.plugin.executeMethod("InsertAndReplaceContentControls", [arrDocuments]);
     *
     * // Change existed content control
     * var arrDocuments = [{
     *  "Props": {
     *       "InternalId": "2_803"
     *   },
     *   "Script": "var oParagraph = Api.CreateParagraph();oParagraph.AddText('New text');Api.GetDocument().InsertContent([oParagraph]);"
     *}]
     * window.Asc.plugin.executeMethod("InsertAndReplaceContentControls", [arrDocuments]);

It should keep your font\style, but please check it out and let us know if something goes wrong.