I have a requirement for loading multiple Swagger-UI components on one page on AEM6.5.
My component template in AEM6.5 looks like this:
<sly data-sly-use.model="xxx.aem.component.content.SwaggerModel"
data-sly-use.template="core/wcm/components/commons/v1/templates.html"
data-sly-use.clientlib="/libs/granite/sightly/templates/clientlib.html">
</sly>
<sly data-sly-call="${clientlib.all @ categories='xxx.ui.swagger-ui'}"/>
<sly data-sly-call="${template.placeholder @ isEmpty=!model.defined}"></sly>
<div data-sly-test="${model.defined}">
<h1 class="t-title">
${model.title}
</h1>
<div id="${model.uniqueId}"></div>
<sly data-sly-test="${model.defined}" data-sly-call="${swaggerScript @ path=model.swaggerYamlPath, name=model.swaggerYamlName, dom_id=model.uniqueId}"></sly>
</div>
<template data-sly-template.swaggerScript="${ @ path, name, dom_id}">
<script>
window.onload = function () {
window.ui = SwaggerUIBundle({
urls: [
{url: "${path @ context='text'}", name: "${name @ context='text'}"},
],
dom_id: '#${dom_id @ context='text'}',
deepLinking: true,
filter: true,
presets: [
SwaggerUIBundle.presets.apis,
SwaggerUIStandalonePreset
],
plugins: [
SwaggerUIBundle.plugins.DownloadUrl
],
layout: 'StandaloneLayout'
});
};
</script>
</template>
The problem is that no matter I use the unique ID only one swagger component will render on the page and the other will not. I can see the swagger components are correctly loaded in the DOM but as already mentioned only one will render.
In the example below only the id="swagger-ui-1110306185"
will render and id="swagger-ui-1671020283"
will not render.
<div class="swagger">
<link rel="stylesheet" href="/etc.clientlibs/xxx/clientlibs/static/swagger-ui.min.css" type="text/css">
<script src="/etc.clientlibs/xxx/clientlibs/static/swagger-ui.min.js"></script>
<div>
<h1 class="t-title">
Here goes the optional title for the Swagger component
</h1>
<div id="swagger-ui-1671020283"></div>
<script>
window.onload = function () {
window.ui = SwaggerUIBundle({
urls: [
{url: "/content/dam/yaml-files/account-information-service-api-v2-of-fi.yaml", name: "account-information-service-api-v2-of-fi"},
],
dom_id: '#swagger-ui-1671020283',
deepLinking: true,
filter: true,
presets: [
SwaggerUIBundle.presets.apis,
SwaggerUIStandalonePreset
],
plugins: [
SwaggerUIBundle.plugins.DownloadUrl
],
layout: 'StandaloneLayout'
});
};
</script>
</div>
</div>
<div class="swagger">
<div>
<h1 class="t-title">
</h1>
<div id="swagger-ui-1110306185"></div>
<script>
window.onload = function () {
window.ui = SwaggerUIBundle({
urls: [
{url: "/content/dam/yaml-files/consent-flow-api-v2-of-fi.yaml", name: "consent-flow-api-v2-of-fi"},
],
dom_id: '#swagger-ui-1110306185',
deepLinking: true,
filter: true,
presets: [
SwaggerUIBundle.presets.apis,
SwaggerUIStandalonePreset
],
plugins: [
SwaggerUIBundle.plugins.DownloadUrl
],
layout: 'StandaloneLayout'
});
};
</script>
</div>
</div>
Here is what worked:
AEM Template:
<div data-sly-test="${model.defined}" data-sly-attribute="${model.dataAttributes}">
<h1 class="t-title">
${model.title}
</h1>
<div id="${model.uniqueId}"></div>
</div>
AEM TypeScript:
declare global {
const SwaggerUIStandalonePreset: any;
const SwaggerUIBundle: any;
}
export class Swagger {
static ID = 'swagger';
static selectors = {
self: `[data-${CoreComponentUtil.NS}-is='${Swagger.ID}']`,
};
private config: CompConfig;
private name: string;
private path: string;
private domId: string;
constructor(config: CompConfig) {
this.init(config);
}
private init(config: CompConfig): void {
this.config = config;
// prevents multiple initialization
config.element.removeAttribute(`data-${CoreComponentUtil.NS}-is`);
this.name = config.element.getAttribute('data-swagger-name');
this.path = config.element.getAttribute('data-swagger-path');
this.domId = config.element.getAttribute('data-swagger-dom-id');
try {
new SwaggerUIBundle({
urls: [
{url: this.path, name: this.name},
],
dom_id: '#' + this.domId,
deepLinking: true,
filter: true,
presets: [
SwaggerUIBundle.presets.apis,
SwaggerUIStandalonePreset,
],
plugins: [
SwaggerUIBundle.plugins.DownloadUrl,
],
layout: 'StandaloneLayout',
});
} catch (e) {
console.log('Could not create Swagger object for ' + this.path);
}
}
}
onReady(() => {
initComponent(Swagger);
});
AEM Model:
public String getSwaggerYamlPath() {
return swaggerYamlPath;
}
public String getSwaggerYamlName() {
return parseYamlFileName(swaggerYamlPath);
}
public String getUniqueId() {
return new StringBuilder().append("swagger-ui").append("-").append(String.valueOf(Math.abs(resource.getPath().hashCode() - 1))).toString();
}
@Override
public Map<String, String> getDataAttributes() {
Map<String, String> attributes = new HashMap<>(super.getDataAttributes());
if (isDefined()) {
attributes.put("data-swagger-name", getSwaggerYamlName());
attributes.put("data-swagger-path", getSwaggerYamlPath());
attributes.put("data-swagger-dom-id", getUniqueId());
}
return attributes;
}