How to use tinymce.confluence.MacroUtils.updateMacro()

I’m trying to update my macro in the editor after a user has given some input for the macro parameters (can do this in the macro property panel). I tried to use the tinymce.confluence.MacroUtils.insertMacro(e,t) method, but it replaces the macro. My goal is that only the macro parameters are adjusted to the input. When just overwriting the macro parameters with the new ones, then the new options will be changed for view mode. But I also want to dynamicaly adjust the image placeholder. I found out that there exists the tinymce.confluence.MacroUtils.updateMacro(e,t,n,r) method, but I can’t find any information about the needed parameters or a documentation on how to use it. Does someone know where I can find this information or has an example on how to use this method?

Thanks for any help.

I know I’ve used this before, but I cannot find that code right now. Maybe it will help you to know that the signature of the method you are looking at is updateMacro: function (updatedParameters, updatedMacroBody, macroName, existingMacroNode). Although internally, that method also just calls the insertMacro method with the parameters provided.

I don’t think I completely understand what exactly you are trying to achieve. What is the difference between replacing the macro and overwriting its parameters? In both cases there will be a placeholder with the right parameters, won’t there?

Thank you for the info. Sorry if I haven’t clearly explained what I’m trying to do. I generate a custom image placeholder with the parameters with a servlet and override the getImagePlaceholder() method. The user can now change the parameters in the macro property panel. And now I’m looking for a way that I can “rerender” the image placeholder with the new parameters. But when I use the insertMacro() method I replace the macro with a new one with the new parameters and have to close the macro property panel (because it belongs to the “old macro”). My goal is to update the image placeholder without having to close the panel.

It has been a long time since I last used macro property panels and macros with custom placeholders, so I’m not sure if I will be able to help you here.

I had a quick look at some old code where I was changing the macro parameters from a property panel, and it looks like back then I just reopened the property panel after updating the Macro. This is roughly the old code, I’m not sure if it still works, but maybe you find something useful in it:

function openPropertyPanel(macroNode) {
    let params = Confluence.MacroParameterSerializer.deserialize(macroNode.getAttribute('data-macro-parameters'));

    var buttons = [
        {
            className: 'macro-placeholder-property-panel-edit-button',
            text: AJS.I18n.getText("property.panel.macro.edit"),
            click: function () {
                AJS.Confluence.PropertyPanel.destroy();

                params.data = "newData";

                tinymce.confluence.MacroUtils.insertMacro({
                    contentId: Confluence.Editor.getContentId(),
                    macro: {
                        name: 'my-macro',
                        params: params,
                        defaultParameterValue: '',
                        body: ''
                    }
                }, macroNode).then((newNode) => {
                    openPropertyPanel(newNode);
                });
            }
        }
    ];

    AJS.Confluence.PropertyPanel.createFromButtonModel('image', macroNode, buttons, { anchorIframe: AJS.Rte.getEditorFrame() });
}

AJS.Confluence.PropertyPanel.Macro.registerInitHandler(function(macroNode) {
    setTimeout(() => {
        openPropertyPanel(macroNode);
    }, 0);
}, "my-macro");

If you want to update the macro parameters without replacing the macro placeholder, I think you just have to change the data-macro-parameters attribute on the macro placeholder element. Looking at the code above, it looks like that would be done approximately like this:

const params = Confluence.MacroParameterSerializer.deserialize(macroPlaceholderNode.getAttribute("data-macro-parameters"));
// Now change params
macroPlaceholderNode.setAttribute("data-macro-parameters", Confluence.MacroParameterSerializer.serialize(params));

Thanks candid for your example code. I didn’t know that the insertMacro() will give the new node back. I now update the placeholder in three steps -> destroy property panel, insertMacro(), create property panel. This would be my code (works):

let updateMacro = (macroPlaceholder, parameters) => {
    Confluence.PropertyPanel.destroy();
    let macroRenderRequest = {
        contentId: Confluence.Editor.getContentId(),
        macro: {
            name: macroPlaceholder.dataset.macroName,
            params: parameters,
            body: ""
        }
    }
    tinymce.confluence.MacroUtils.insertMacro(macroRenderRequest, macroPlaceholder).then((newNode) => {
        let options = {
            originalHeight: false,
            anchorIframe: AJS.Rte.getEditorFrame()
        }
        Confluence.PropertyPanel.createFromButtonModel("macro", newNode, getDefaultButtonsArray(newNode), options);
    });
}

let getDefaultButtonsArray = (newNode) => {
    let buttons = [];
    buttons.push({
        className: "macro-placeholder-property-panel-edit-button",
        text: "Edit",
        click: function() {
            AJS.Confluence.PropertyPanel.destroy();
            tinymce.confluence.macrobrowser.editMacro(newNode);
        }
    });
    buttons.push({
        className: "macro-placeholder-property-panel-remove-button",
        text: "Remove",
        click: function() {
            AJS.Confluence.PropertyPanel.destroy();
            AJS.Rte.getEditor().execCommand('mceConfRemoveMacro', newNode);
        }
    });
    return buttons;
}

I know that changing the data-macro-parameters will work updating them, but sadly it doesn’t “rerender” the image placeholder.
If someone has a better idea or would go at it differently I’m interested to hear.