1.3. Render File
Take a look at the i18n page for more information on translating widgets.
Widgets are stand alone JS applications, but a component library only has components. To bridge that gap we need to
create a render file. This is a file that will render a component in a <div>
that the CMS will print on the page. The
JavaScript application will render inside that <div>
.
Rendering a component is heavily dependent on the JS framework you are using. This step will look different for React, Vue, Angular, Web Components, ...
- Web Components
- React
- Vue
- Angular
require('./toast-notification');
/**
* Renders the widget.
*
* It renders a react application as the widget.
*
* @param {string} instanceId
* The already present HTML element ID where the react app will be rendered.
* @param {string} langCode
* The language code for internationalization purposes.
* @param {string} origin
* Protocol and hostname where a JSONAPI endpoint is available.
* @param {Function} cb
* A callback that executes after the widget has been rendered.
*
* @return {Promise<void>}
* The async render function.
*/
module.exports = async function(instanceId, langCode, origin, cb) => {
const element = document.getElementById(instanceId);
if (!element) {
return;
}
// Just print the custom HTML element inside of the div and call the callback.
element.innerHTML = `<bx-toast-notification
title="${element.getAttribute('data-title')}"
subtitle="${element.getAttribute('data-description')}"
caption="${element.getAttribute('data-caption')}"
kind="${element.getAttribute('data-kind')}"
/>`;
// Execute the callback so the parent process knows we are done rendering.
cb(element);
};
import React from 'react';
import ReactDOM from 'react-dom';
import './index.scss';
import ToastNotification from './components/Widget';
import * as serviceWorker from './core/bin/serviceWorker';
import { IntlProvider } from 'react-intl';
import i18n from './core/bin/i18n.js';
/**
* Renders the widget.
*
* It renders a react application as the widget.
*
* @param {string} instanceId
* The already present HTML element ID where the react app will be rendered.
* @param {string} langCode
* The language code for internationalization purposes.
* @param {string} origin
* Protocol and hostname where a JSONAPI endpoint is available.
* @param {Function} cb
* A callback that executes after the widget has been rendered.
*
* @return {Promise<void>}
* The async render function.
*/
module.exports = async function(instanceId, langCode, origin, cb) => {
const element = document.getElementById(instanceId);
const translation = new i18n(langCode || serviceWorker.getUrlLocale());
ReactDOM.render(
<React.StrictMode>
<IntlProvider locale={translation.locale} messages={translation.messages}>
<ToastNotification
title={element.getAttribute('data-title')}
subtitle={element.getAttribute('data-description')}
caption={element.getAttribute('data-caption')}
kind={element.getAttribute('data-kind')}
/>
</IntlProvider>
</React.StrictMode>,
element,
() => cb(element),
);
serviceWorker.unregister();
}
I have not worked with Vue widgets yet. If you have worked with Vue and you want to provide the example code, please find the Edit link below and edit this page.
I have not worked with Angular widgets yet. If you have worked with Angular and you want to provide the example code, please find the Edit link below and edit this page.
Note that the editorial input from the CMS is made available to you as data attributes in the wrapping <div>
. You can
get those values with element.getAttribute('data-<propertyname>')
. This is how you feed the editorial input to the
JavaScript component props.