How to get AJS.contextPath() in AUI 8?

I have been using the contextPath method in AJS to get the URL of rest resource like this:
var settingsAdminUrlPostUrl = AJS.contextPath() + "/rest/prnfb-admin/1.0/settings";

But this method seems to be unavailable in 8.x of AUI:
https://docs.atlassian.com/aui/8.5.1/docs/helper.html

How do I get the contextPath when using AUI 8.x?

Relates to this issue (I would be grateful for any help on this):

1 Like

Hi Tomas, big fan of your plugin. We were very sad to see that the plugin wasn’t available in Data Center and it was difficult to work it out of our workflow. Very happy to see you continuing to develop it.

I think you could be using navbuilder from javascript api yes?
https://docs.atlassian.com/bitbucket-server/docs/6.6.2/reference/javascript/bitbucket_util_navbuilder.html

Happy to help in any way.

Thanks!

I had a look at those docs. Cannot figure out how to rewrite this line to use navbuilder:

And I also see AJS.template is deprecated, which really feels like a stab in the back… perhaps not even worth spending time on this without solving that first.

And now my question is marked as spam =) Working with Atlassian products is an absolutely terrible experience!

Hey @tomas.bjerre85, what you can do instead of using the AJS.contextPath is use the AMD module called wrm/context-path. The module exposes a single function you can call in your code e.g.:

define('my-module', ['wrm/context-path'], function(contextPath) {
  console.log(contextPath);
});

You should consider adding a dependency on this web-resource com.atlassian.plugins.atlassian-plugins-webresource-plugin:context-path to ensure your code has all the required dependencies.

Here you can find the source code of this module:

Let me know if that worked for you.

Thanks,
Maciej

3 Likes

As for the missing AJS.template module, you can try loading the module manually:

AJS.template is undefined

Cannot read property “fill” of undefined You need to explicitly import this function now.

In the Node package:

  • Add a dependency on @atlassian/aui-template to your package.json file.
  • This package uses the UMD pattern for its export. When treating it as a module, use its default export. If no module system is available, it exports to window.ajstemplate.

In the Atlassian plugin:

  • Add a web-resource dependency on com.atlassian.auiplugin:template

source: https://docs.atlassian.com/aui/8.0.0/docs/upgrades/aui-8.html

To be completely honest I have never tried that approach but I hope this will work for you.

Thanks,
Maciej

I’ve used Soy Templates to great success for dynamic elements I can create in Javascript. I’d suspect that would work really well Thomas, but it would mean reworking his plugin to work with Soy instead.

Thanks @madamczak for the response.

Regarding:

How do I require that template code?

...
define('plugin/prnfb/utils', [
 'what goes here?'
], function(ajsTemplate) {
...

I was expecting that to be well documented here:
https://docs.atlassian.com/aui/8.5.1/docs/template.html

And I am also wondering if there is any point in spending time on that as it is deprecated?

If you load the com.atlassian.auiplugin:template web-resource dependency then it looks like you can depend on @atlassian/aui.

If you bundle your code using e.g. webpack and you depend on the ‘@atlassian/aui-template’ NPM package, then I think you should try to import it using NPM package name.

I’ve used neither of this web resource or NPM package so I can’t confirm that will work.

You could consider switching to soy templates or something more modern like e.g. React. I don’t know how big is your code so switching to React might be overkill as well.

Hi @madamczak,

Can you explain to me the rational about making something promise/callback based that is obviously known at page load and should be available synchronously?

By requiring me to dynamically load a module, it means that for instance when using React, I will have to add context resolution to my component state during the componentDidMount() call, use React Context API or an HoC instead of being able to construct the URL during rendering.

Hey @remie,

The wrm/context-path is a module that is defined in the browser runtime. The AMD module loader will not have to try to load it from the server. Once you specify all the web-resource XML dependencies for WRM module, you will get them loader in the runtime. Additional pros of using the wrm/* module is that you don’t depend on the global variables anymore and you should be able to write a unit test that can mock the wrm/* dependency.

Like I wrote in the previous paragraph. The wrm/* are not dynamically loaded modules. You could write your code using either AMD or ESM (with the help of babel and webpack):

define('my-react-component', ['wrm/context-path'], function(contextPath) {
  console.log(contextPath);

  const url = `${contextPath()}/some/url?with=param`;

  return function MyReactComponent(props) {
      <div>{url}</div>
  };
});

or if you prefer ESM:

import contexPath from 'wrm/context-path';

const url = `${contextPath()}/some/url?with=param`;

export default function MyReactComponent(props) {
    <div>{url}</div>
};

I hope that brings more clarity to the discussion.

Thanks,
Maciej