# Add a Configuration MFE in App Builder
Entando MFEs can be customized through an App Builder feature that uses a specialized micro frontend. This tutorial splits the process into 4 steps:
- Modify an existing MFE (the target MFE) to take a configuration option
- Create a new MFE (the config MFE) to provide a user interface for the configuration option
- Set up the target MFE to use the configuration provided by the config MFE
- Publish and test the configurable MFE
# Prerequisites
# Step 1: Add a Configuration Option to a Target MFE
Start by adding a configuration option to an existing MFE. If you don't already have one, you can create it via the React MFE tutorial.
# Add an Attribute to the Custom Element
- Replace the contents of
src/custom-elements/WidgetElement.js
with the following code to add attribute handling to the custom element and re-render the app when an attribute changes. This enables the Entando-providedconfig
to be passed as a property to the React root component (App
).
import React from 'react';
import { createRoot } from 'react-dom/client';
import App from '../App';
const ATTRIBUTES = {
config: 'config'
};
class WidgetElement extends HTMLElement {
static get observedAttributes() {
return Object.values(ATTRIBUTES);
}
connectedCallback() {
this.mountPoint = document.createElement('div');
this.appendChild(this.mountPoint);
this.root = createRoot(this.mountPoint);
this.render();
}
attributeChangedCallback(attribute, oldValue, newValue) {
if (!WidgetElement.observedAttributes.includes(attribute)) {
throw new Error(`Untracked changed attributes: ${attribute}`)
}
if (this.mountPoint && newValue !== oldValue) {
this.render();
}
}
render() {
const attributeConfig = this.getAttribute(ATTRIBUTES.config);
const config = attributeConfig && JSON.parse(attributeConfig);
this.root.render(
<App config={config} />
);
}
}
customElements.define('simple-mfe', WidgetElement);
- Replace the contents of
src/App.js
with the following. This component now receives theconfig
property and displays thename
parameter it contains. This turns the static component from the React MFE tutorial into a more dynamic component.
import './App.css';
function App({config}) {
const { params } = config || {};
const { name } = params || {};
return (
<div className="App">
<header className="App-header">
<p>
Hello, {name}!
</p>
</header>
</div>
);
}
export default App;
- For test purposes, add a configuration file
public/mfe-config.json
with the following content:
{
"params": {
"name": "Jane Smith"
}
}
- Replace the
body
ofpublic/index.html
with the following. This allows you to set the MFEconfig
attribute and test locally with the same configuration structure provided by Entando.
<simple-mfe/>
<script>
function injectConfigIntoMfe() {
fetch('%PUBLIC_URL%/mfe-config.json').then(async response => {
const config = await response.text()
const mfeEl = document.getElementsByTagName('simple-mfe')[0]
mfeEl.setAttribute('config', config)
})
}
injectConfigIntoMfe()
</script>
- Start the app and confirm that "Hello, Jane Smith!" is displayed. Use Ctrl+C to close the app.
ent bundle run simple-mfe
# Step 2: Create a Config MFE
Next, create a new MFE for managing the configuration option. These steps are very similar to the React MFE tutorial.
- Add a new microfrontend to your bundle project:
ent bundle mfe add simple-mfe-config --type=widget-config
- Generate a new React app:
npx create-react-app microfrontends/simple-mfe-config --use-npm
- Start the app:
ent bundle run simple-mfe-config
- Add a
src/WidgetElement.js
component with the following content to set up the custom element for the config MFE.
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
class WidgetElement extends HTMLElement {
constructor() {
super();
this.reactRootRef = React.createRef();
this.mountPoint = null;
}
get config() {
return this.reactRootRef.current ? this.reactRootRef.current.state : {};
}
set config(value) {
return this.reactRootRef.current.setState(value);
}
connectedCallback() {
this.mountPoint = document.createElement('div');
this.appendChild(this.mountPoint);
this.render();
}
render() {
ReactDOM.render(<App ref={this.reactRootRef} />, this.mountPoint);
}
}
customElements.define('simple-mfe-config', WidgetElement);
App Builder integration
- A config MFE must retain its state in a
config
property - The App Builder supplies the
config
property when the config MFE is rendered - When a user saves the form, the App Builder automatically persists the configuration through Entando APIs
- Replace the contents of
src/App.js
with the following to add a simple form for managing a singlename
field
import React, {Component} from 'react';
class App extends Component {
constructor(props) {
super(props);
this.state = {
name: props.name
};
}
handleChange = e => {
const input = e.target;
this.setState({
[input.name]: input.value,
});
};
render() {
const { name } = this.state;
return (
<div>
<h1>Simple MFE Configuration</h1>
<div>
<label htmlFor="name">Name </label>
<input id="name" name="name" defaultValue={name} type="text" onChange={this.handleChange} />
</div>
</div>
);
}
}
export default App;
TIP
- When the config MFE is displayed within the App Builder, the App Builder styles will be applied.
- Replace the contents of
src/index.js
with the following:
import './index.css';
import './WidgetElement';
- For test purposes, add a configuration file
public/mfe-config.json
with the following content. Note: the JSON for a config MFE contains just parameters so it is simpler than the JSON for a target MFE.
{
"name": "John Brown"
}
- Replace the
body
ofpublic/index.html
with the following. This allows you to set the config MFE parameters and test locally.
<simple-mfe-config/>
<script>
function injectConfigIntoMfe() {
fetch('%PUBLIC_URL%/mfe-config.json').then(async response => {
const config = await response.json()
const mfeEl = document.getElementsByTagName('simple-mfe-config')[0]
mfeEl.config = config
})
}
injectConfigIntoMfe()
</script>
# Step 3: Configure the Target MFE to Use the Config MFE
- Edit the
entando.json
and add these properties to the target MFE in order to connect the config MFE to the target MFE and specify the available params.
"configMfe": "simple-mfe-config",
"params": [
{
"name": "name",
"description": "The name for Hello World"
}
]
# Step 4: Publish and Test the Configurable MFE
You can now build and install the bundle. See the Build and Publish tutorial for more details on the steps.
Test the full setup by adding the widget into an existing page. The config MFE should be displayed when the widget is first added to the page.
Fill out the
name
field and clickSave
. You can update the widget configuration at any point by clickingSettings
from the widget actions in the Page Designer.Publish the page and confirm the target MFE is configured and displays correctly.