saveMacro function fails (TypeError: Cannot read property 'parameters' of undefined)

Hi,

I created a Dynamic Content Macro with a Custom Macro Editor using a Handlebars template.

As described in the reference:
Macro Editor Reference
and in a guide:
Macro custom editor Guide
I tried both functions:

AP.require(["confluence", "dialog"], function (confluence, dialog) {
    function onSubmit() {
        var macroParams = {
            myParameter: value
        };
        confluence.saveMacro(macroParams);
        confluence.closeMacroEditor();
        return true;
    }

    dialog.getButton("submit").bind(onSubmit);
});

and

AP.dialog.getButton("submit").bind(function () {
            confluence.saveMacro({
                'url': data.url
            });
            AP.confluence.closeMacroEditor();
            return true;
        });

I always get an error in the console:

TypeError: Cannot read property 'parameters' of undefined
    at m (transformers.ts:80)
    at I (index.ts:344)
    at async Object.onComplete (index.ts:152)

My guess at the moment is that the Handlebars template does not contain all imports. But I don’t know which imports are necessary.

(if I don’t use a custom macro editor, I don’t get any error messages and can access MacroData (Parameter defined in atlassian-connect.json)

HI @HendrikSchneider,

Does this error occur just after your call to confluence.saveMacro() in both cases? If you’re not sure, are you able to add a debugger; statement to your code to determine which of your calls is the last to be executed before the error occurs?

Regards,
Dugald

Hi @HendrikSchneider,

One more question, do you have a parameters property in your dynamic content macro definition in your Connect descriptor. See also the documentation of the dynamic content macro module and macro input parameter.

Regards,
Dugald

Try adding an empty macroBody when you call saveMacro.

Example

AP.confluence.saveMacro({
    'url': data.url
}, '');

The documentation doesn’t seem to be accurate about the behaviour of saveMacro.

I had the same issue, but adding the empty body '' resolved the error for me.

There must be some other factor at play because the error doesn’t occur for me. I’ll continue looking into this.

Thanks @dmorrow.

It’s possible that there could be some other issue in the background of our setups, because I had another issue with saveMacro not behaving as expected (Confluence.saveMacro does not save macro body).

Would be interesting to see what the real problem is.

1 Like

Thanks @JoeyL. The dynamic macro API is complicated and I don’t profess to be an expert, but I’ll dig a little deeper.

1 Like

Hi @HendrikSchneider,

I believe the stack trace you provided is from the host frame and not your app iframe so it has nothing to do with your Handlebars setup or dependencies. It is a bug in the Confluence front end code because it incorrectly assumes a particular ADF attrs node has a child node parameters, but I need to gather a little bit more information to help reproduce this. Does this problem occur no matter where you insert your macro? Are you able to investigate a little further on your side.

Regards,
Dugald

Hi @dmorrow

So I’ve tried a few things now.

  1. I think the original error message:
TypeError: Cannot read property 'parameters' of undefined
    at m (transformers.ts:80)
    at I (index.ts:344)
    at async Object.onComplete (index.ts:152)

was because i actually did not include the {{hostScriptUrl}} in the layout template. So the error message disappeared.

I don’t get an error message, but saveMacro still doesn’t have any function for me.

Even after I added an Empty Macro Body like:

  1. So I simply created a new template project (clone of the hello wolrd macro addon).

I assume that I don’t fully understand how the saveMacro function works. I’ll post my code here, maybe I’m missing something.

App descriptor

"modules": {
            "dynamicContentMacros": [{
                "key": "helloworld-macro",
                "name": {
                    "value": "Hello World Macro"
                },
                "url": "/macro?message={message}&myParameter={myParameter}",
                "description": {
                    "value": "Says 'Hello World'."
                },
                "outputType": "block",
                "bodyType": "rich-text",
                "parameters": [{
                        "identifier": "message",
                        "name": {
                            "value": "Message"
                        },
                        "description": {
                            "value": "Send a message"
                        },
                        "type": "string"
                    },
                    {
                        "identifier": "myParameter",
                        "name": {
                            "value": "My Parameter"
                        },
                        "description": {
                            "value": "Send a message, too"
                        },
                        "type": "string"
                    }
                ],
                "editor": {
                    "url": "/macro-editor",
                    "editTitle": {
                        "value": "Edit Macro"
                    },
                    "insertTitle": {
                        "value": "Insert Macro"
                    }
                }
            }]
        }

Routes

app.get('/macro', addon.authenticate(), function(req, res) {
        res.render('hello-world', {
            title: 'Atlassian Connect'
        });
    });
app.get('/macro-editor', addon.authenticate(), function(req, res) {
        return res.render('hello-world-editor');
    });

Handlebar Template hello-world

{{!< layout}}
<p id="inhalt"></p>
<script>
    AP.confluence.getMacroBody(function(body){
        document.getElementById('inhalt').innerHTML = body;
    });
    AP.confluence.getMacroData(function(data){
        alert(data.message);
        alert(data.myParameter);
    });
</script>

Handlebar Template hello-world-editor

{{!< layout}}
<p>Hello there!</p>
<script>
    AP.require(["confluence", "dialog"], function (confluence, dialog) {
    function onSubmit() {
        confluence.saveMacro({myParameter: 'Hello Message!'});
        confluence.closeMacroEditor();
        return true;
    }
    dialog.getButton("submit").bind(onSubmit);
    });
</script>
  • If I do not use the custom editor, then I get the values of my 2 parameters on the page.

  • If i use the custom editor, the message Parameter will be undefined, which is alright, but the myParameter seems not be saved.

Now i get some other Error Messages:

Since I am still quite new to programming, I guess I just overlooked something essential.

1 Like

Hi @HendrikSchneider,

Thanks for these details. at least we’ve solved the stack trace. Can you do a quick test to see if changing the bodyType to plain-text. i.e. "bodyType": "plain-text" .

Regards,
Dugald

Thanks for the quick reply @dmorrow

So changing the bodyType to plain-text has granted access to the parameter “myParameter”:

image

the alert Function works now.
But for my Macro i will have to use the rich-text Format, because, for example, I want to enter formatted tables into the macro body.

The Uncaught ReferenceError also disappeared, after I injected some newer AUI.JS versions in the Layout Handlebar Template.

Thanks for confirming that @HendrikSchneider. From my own testing, I suspected the change of bodyType from rich-text to plain-text would make a difference, but I’m not sure why. You may be able to avoid changing back to rich-text if your macro view could be generated from the macro parameters rather than rendering the macro body directly.

Regards,
Dugald

I think i will split the macro in 2 parts.

One macro with a static ID parameter with the body that should be rendered directly and a second macro that will handle the view with a custom macro editor.

Maybe there will be a solution for the problem in the future.

Thank you for your help @dmorrow !

Best Regards,
Hendrik

1 Like

Hi guys @dmorrow, @HendrikSchneider

I get the exact same error with a rich-text macro, is there any solution to this issue rather than changing the bodyType? My macro must have rich-text bodyType since it’s an element with a predefined style that users should be able to write their content inside.

thanks.

Hi @TomKeidar,
i just found a workaround. The User has to create 2 Macros, one with Rich-Text and without a body. I store the Macro ID of the rich-text macro as a context property on the page and with the help of the REST API i can get the rich-text body of the macro and process it with the other macro…

But i hope the issue will be fixed someday, as i do not want the user to use 2 macros all the time.

Hi @HendrikSchneider,

Thanks for the quick response but unfortunately this isn’t a possible solution for me.
The macro I’m working on is part of an app we are developing and I can’t ask my users to use 2 macros for this solution.
I hope there is another solution for this issue :confused: