From cbe6764ff5266762e3c39fc34e52a931e90badd4 Mon Sep 17 00:00:00 2001 From: Lydia Pedersen Date: Mon, 19 Sep 2022 18:15:45 -0700 Subject: [PATCH 1/3] ENDOC-507 Widget communication --- .../tutorials/create/mfe/communication.md | 721 ++++-------------- 1 file changed, 147 insertions(+), 574 deletions(-) diff --git a/vuepress/docs/next/tutorials/create/mfe/communication.md b/vuepress/docs/next/tutorials/create/mfe/communication.md index 1106777648..4f78544de7 100644 --- a/vuepress/docs/next/tutorials/create/mfe/communication.md +++ b/vuepress/docs/next/tutorials/create/mfe/communication.md @@ -6,651 +6,224 @@ sidebarDepth: 2 ::: tip Recommended Learning - Tutorial: [Create a React Micro Frontend](react.md) -- Tutorial: [Create an Angular Micro Frontend](angular.md) ::: -Entando supports communication between micro frontends using [Custom Events](https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent), an established web standard. In this tutorial, we build: +Entando supports communication between micro frontends (MFEs) using [Custom Events](https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent), an established web standard. The MFEs can use either the same or different JavaScript frameworks. In this tutorial, we build: -- A React micro frontend that publishes an event -- A React micro frontend that listens to an event -- An Angular micro frontend that publishes an event to a React micro frontend +- A React MFE that publishes an event +- A React MFE that listens to an event +## Prerequisites -## Publisher +- 2 simple React apps: One will be modified to publish an event while the other will be modified to subscribe to an event. Refer to the [simple React app tutorial](react.md#create-a-react-app-in-an-entando-bundle) to create an MFE and import and test the custom element. -Create a simple app to publish an event. +## Modify the Publisher MFE -``` bash -npx create-react-app publisher-widget --use-npm -``` - -Start the app. - -``` bash -cd publisher-widget -``` - -``` bash -npm start -``` - -### Create Custom Event - -Next, add event firing logic. - -Add a new file `publisher-widget/src/PublisherWidgetElement.js`. - -``` js -import React from 'react'; -import ReactDOM from 'react-dom'; -import App from './App'; - -const EVENTS = { - greeting: 'greeting', -}; +1. To add a custom event, create the file `publisher-widget/src/PublisherWidgetElement.js`: -class PublisherWidgetElement extends HTMLElement { + ``` js + import React from 'react'; + import ReactDOM from 'react-dom'; + import App from './App'; - constructor() { - super(); - this.onGreet = name => this.publishWidgetEvent(EVENTS.greeting, { name }); - } + const EVENTS = { + greeting: 'greeting', + }; - connectedCallback() { - this.mountPoint = document.createElement('div'); - this.appendChild(this.mountPoint); - this.render(); - } + class PublisherWidgetElement extends HTMLElement { - publishWidgetEvent(eventId, detail) { - const widgetEvent = new CustomEvent(eventId, { detail }); - window.dispatchEvent(widgetEvent); - } + constructor() { + super(); + this.onGreet = name => this.publishWidgetEvent(EVENTS.greeting, { name }); + } - render() { - ReactDOM.render(, this.mountPoint); - } -} + connectedCallback() { + this.mountPoint = document.createElement('div'); + this.appendChild(this.mountPoint); + this.render(); + } -customElements.define('publisher-widget', PublisherWidgetElement); + publishWidgetEvent(eventId, detail) { + const widgetEvent = new CustomEvent(eventId, { detail }); + window.dispatchEvent(widgetEvent); + } -export default PublisherWidgetElement; -``` + render() { + ReactDOM.render(, this.mountPoint); + } + } -- In the `CustomEvent` constructor, `detail` is the specific name to use in the event payload, as per the [DOM specification](https://dom.spec.whatwg.org/#interface-customevent). + customElements.define('publisher-widget', PublisherWidgetElement); -#### Import Custom Element + export default PublisherWidgetElement; + ``` -Update `publisher-widget/src/index.js`. + In the `CustomEvent` constructor, `detail` denotes the specific name to use in the event payload per the [DOM specification](https://dom.spec.whatwg.org/#interface-customevent). -``` js -import './index.css'; -import './PublisherWidgetElement'; -``` +2. Update `publisher-widget/src/App.js` to dispatch an event: -#### Test Custom Element + ``` js + import React from 'react'; + import './App.css'; + + class App extends React.Component { + constructor(props) { + super(props); + this.state = { name: ''}; + } -Update `publisher-widget/public/index.html`, and view it in the browser. + handleNameChange(value) { + this.setState(prevState => ({ + ...prevState, + name: value, + })); + } -``` html - - - - ... - -``` + render() { + const { name } = this.state; + const { onGreet } = this.props; + return ( +
+

Send a greeting

+ + this.handleNameChange(e.target.value)} value={name} /> + +
+ ); + } + } -### Update React App to Dispatch Event - -Update `publisher-widget/src/App.js`. - -``` js -import React from 'react'; -import './App.css'; - -class App extends React.Component { - constructor(props) { - super(props); - this.state = { name: ''}; - } - - handleNameChange(value) { - this.setState(prevState => ({ - ...prevState, - name: value, - })); - } - - render() { - const { name } = this.state; - const { onGreet } = this.props; - return ( -
-

Send a greeting

- - this.handleNameChange(e.target.value)} value={name} /> - -
- ); - } -} - -export default App; -``` + export default App; + ``` -### Test Event Dispatcher +3. Enter the following in the JavaScript console of your browser: -In the JavaScript console of your browser, enter: + ``` js + window.addEventListener('greeting', (evt) => console.log('Hello', evt.detail.name)) + ``` -``` js -window.addEventListener('greeting', (evt) => console.log('Hello', evt.detail.name)) -``` +4. To test the event dispatcher, write something in the text field and click the "Say hello!" button -Write something in the text field. Click the "Say hello!" button and take a look at the JS console. It will show the event message. +5. Confirm the event message appears in the JS console ::: tip Congratulations! -You’ve now published a custom event. +You’ve now published a custom event ::: -## Subscriber +## Modify the Subscriber MFE -Next, let’s create the subscriber. +1. To add an event listener, create the file `subscriber-widget/src/SubscriberWidgetElement.js`: -``` bash -npx create-react-app subscriber-widget --use-npm -``` + ``` js + import React from 'react'; + import ReactDOM from 'react-dom'; + import App from './App'; -Start the app. + const EVENTS = { + greeting: 'greeting', + }; -``` bash -cd subscriber-widget -``` - -``` bash -npm start -``` + class SubscriberWidgetElement extends HTMLElement { -### Add Event Listener + constructor() { + super(); + this.name = null; + this.subscribeToWidgetEvent(EVENTS.greeting, (evt) => this.onGreeting(evt.detail.name)); + } -Add a new file `subscriber-widget/src/SubscriberWidgetElement.js`. + connectedCallback() { + this.mountPoint = document.createElement('div'); + this.appendChild(this.mountPoint); + this.render(); + } -``` js -import React from 'react'; -import ReactDOM from 'react-dom'; -import App from './App'; + subscribeToWidgetEvent(eventType, eventHandler) { + window.addEventListener(eventType, eventHandler); + } -const EVENTS = { - greeting: 'greeting', -}; + onGreeting(name) { + this.name = name; + this.render(); + } -class SubscriberWidgetElement extends HTMLElement { + render() { + ReactDOM.render(, this.mountPoint); + } + } - constructor() { - super(); - this.name = null; - this.subscribeToWidgetEvent(EVENTS.greeting, (evt) => this.onGreeting(evt.detail.name)); - } + customElements.define('subscriber-widget', SubscriberWidgetElement); - connectedCallback() { - this.mountPoint = document.createElement('div'); - this.appendChild(this.mountPoint); - this.render(); - } + export default SubscriberWidgetElement; + ``` +2. Update `subscriber-widget/src/App.js` to display the custom event: - subscribeToWidgetEvent(eventType, eventHandler) { - window.addEventListener(eventType, eventHandler); - } + ``` js + import React from 'react'; + import './App.css'; - onGreeting(name) { - this.name = name; - this.render(); - } + function App({ name }) { + return name ? (

Just got a greeting from {name}

) + : (

Waiting for a greeting...

); + } - render() { - ReactDOM.render(, this.mountPoint); - } -} + export default App; + ``` -customElements.define('subscriber-widget', SubscriberWidgetElement); - -export default SubscriberWidgetElement; -``` +3. To test the event listener, enter the following in the JavaScript console of your browser: -#### Import Custom Element + ``` js + const widgetEvent = new CustomEvent('greeting', { + detail: { + name: 'Pippo' + }, + }); + window.dispatchEvent(widgetEvent); + ``` -Update `subscriber-widget/src/index.js`. - -``` js -import './index.css'; -import './SubscriberWidgetElement'; -``` - -#### Test Micro Frontend - -Update `subscriber-widget/public/index.html`, and view it in the browser. - -``` html - - - - ... - -``` - -### Display Custom Event - -Update `subscriber-widget/src/App.js`. - -``` js -import React from 'react'; -import './App.css'; - -function App({ name }) { - return name ? (

Just got a greeting from {name}

) - : (

Waiting for a greeting...

); -} - -export default App; -``` - -### Test Event Listener - -In the JavaScript console of your browser, enter: - -``` js -const widgetEvent = new CustomEvent('greeting', { - detail: { - name: 'Pippo' - }, -}); -window.dispatchEvent(widgetEvent); -``` - -The custom event should now display in the `subscriber-widget`. +4. Confirm the custom event is displayed in the `subscriber-widget` ::: tip Congratulations! -You’ve now created a micro frontend that listens to custom events. +You’ve now created a micro frontend that listens to custom events ::: ## Add Widgets to App Builder -Now let's add the publisher and subscriber micro frontends in Entando. - -### Create Environment File - -#### Publisher Widget - -1. Create an `.env` file in the project root for the `publisher-widget`. - -2. Open the `.env` file, and enter the `PUBLIC_URL` where the micro frontend will be hosted. - -Example: - -``` -PUBLIC_URL=http://quickstart.192.168.64.34.nip.io/entando-de-app/cmsresources/publisher-widget -``` - -::: tip Notes -- Replace `quickstart.192.168.64.34.nip.io` with the ingress you use to access Entando from your local browser. -- `/entando-de-app/cmsresources/` is your Resource URL. -- `publisher-widget` is the public folder we'll create to host the publisher micro frontend. -::: - -#### Subscriber Widget - -1. Create an `.env` file in the project root for the `subscriber-widget`. - -2. Open the `.env` file, and enter the `PUBLIC_URL` where the micro frontend will be hosted. - -- Use `subscriber-widget` for the name of the public folder we'll create to host the subscriber micro frontend. - -Example: - -``` -PUBLIC_URL=http://quickstart.192.168.64.34.nip.io/entando-de-app/cmsresources/subscriber-widget -``` - -### Run npm build - -#### Publisher Widget - -1. Open a command line, and navigate to the project root of the `publisher-widget`. - -2. Run build. - -``` bash -npm run build -``` - -3. Rename the following generated files in the `build` directory. - -| Example of Generated Build File | Rename to | Function -| :--- | :--- | :--- -| build/static/js/2.f14073bd.chunk.js | `static/js/vendor.js` | Third-party libraries -| build/static/js/runtime-main.8a835b7b.js | `static/js/runtime.js` | Bootstrapping logic -| build/static/js/main.4a514a6d.chunk.js | `static/js/main.js` | App -| build/static/css/main.5f361e03.chunk.css | `static/css/main.css` | Stylesheet - -#### Subscriber Widget - -- Repeat steps 1-3 for the `subscriber-widget`. - -### Create Public Folder - -#### Publisher Widget - -1. Navigate to `Entando App Builder` in your browser. - -2. Go to `Configuration` → `File Browser` → `public` - -3. Click `Create Folder`. - -4. Enter `publisher-widget`. - -5. Click `Save`. - -6. Click `public` → `publisher-widget`. - -7. Create the same folder structure as your generated build directory - -- `publisher-widget/static/css` -- `publisher-widget/static/js` - -8. Upload the files we renamed in the corresponding `js` and `css` folders. - -- `publisher-widget/static/css/main.css` -- `publisher-widget/static/js/main.js` -- `publisher-widget/static/js/runtime.js` -- `publisher-widget/static/js/vendor.js` - -#### Subscriber Widget - -- Repeat steps 1-8 for the `subscriber-widget`. - -### Add Widgets - -#### Publisher Widget - -1. Go to `Entando App Builder` in your browser. - -2. Go to `Components` → `Micro Frontends & Widgets` at the top nav. +To add the publisher and subscriber MFEs to Entando, run the following commands from the root folder of each: -3. Click `Add`. - -4. Enter the following: - -- `Code: publisher_widget` → note: dashes are not allowed -- `Title: Publisher Widget` → for both English and Italian languages -- `Group: Free Access` -- `Custom UI:` - -``` ftl -<#assign wp=JspTaglibs[ "/aps-core"]> - - - - - +``` sh +ent bundle pack +ent bundle publish +ent bundle deploy +ent bundle install ``` -5. Click `Save`. - -#### Subscriber Widget - -Repeat steps 1-5 for the subscriber widget. - -- `Code: subscriber_widget` → note: dashes are not allowed -- `Title: Subscriber Widget` → for both English and Italian languages -- `Group: Free Access` -- `Custom UI:` - -``` ftl -<#assign wp=JspTaglibs[ "/aps-core"]> - - - - - -``` +Refer to the tutorial on how to [publish a bundle project](../pb/publish-project-bundle.md#create-and-deploy-a-bundle-project) for more detailed instructions. ### View on a Page -You can setup the widgets on an existing page (such as the Home page) or [create your own page](../../compose/page-management.md). The following steps assume you'll use the Home page. + +Set up the widgets on an existing page or [create your own page](../../compose/page-management.md). The following steps assume you'll use the `Home` page. 1. Go to `Pages` → `Management` 2. For the `Home` page `(folder icon)`, in the `Actions` column, click the `⋮` icon -3. Click `Edit`. +3. Click `Edit` -4. In the `Settings` section, select a Page Template with more than one frame, e.g. `1-column`: +4. In the `Settings` section, select a Page Template with more than one frame -- `Page Template: 1 Column` +5. Click `Save and Configure` -5. Click `Save and Configure`. +6. From the `WIDGETS` sidebar on the right, drag `Publisher Widget` and `Subscriber Widget` into `Frame 1` and `Frame 2` -6. In the `WIDGETS` sidebar on the right: +7. Click `Publish` -- Drag `Publisher Widget` and `Subscriber Widget` into `Frame 1` and `Frame 2`. +8. To view the `Home` page, scroll up and click `Go to Homepage` -7. Click `Publish`. +9. Enter a greeting in the input field and click the submit button -8. To view the home page, scroll to the top of the page, and click `Go to Homepage`. - -9. Enter a greeting in the input field. Press the submit button. The subscriber widget will update with the greeting. Done! +10. Confirm that the subscriber widget updates to display the greeting ::: tip Congratulations! -You can now communicate between micro frontends with `Custom Events`. +You can now communicate between micro frontends with `Custom Events` ::: -## Angular to React - -We can also communicate between micro frontends using different JavaScript frameworks. - -In this next example, we’ll create an Angular micro frontend to publish an event, and we'll use the React micro frontend we created in the previous section to receive the event. - -### Create Angular Publisher - -``` bash -ng new angular-publisher-widget -``` - -Choose the following options: - -``` bash -? Would you like to add Angular routing? No -? Which stylesheet format would you like to use? CSS -``` - -Serve the application. - -``` bash -cd angular-publisher-widget -``` - -``` bash -ng serve -``` - -#### Convert to Custom Element - -Next, let's convert our Angular app into a custom element. We'll use [Angular elements](https://angular.io/guide/elements) to transform components into custom elements. - -``` bash -ng add @angular/elements -``` - -Replace the contents of `angular-publisher-widget/src/app/app.module.ts`. - -- In this file, we bootstrap the custom element using the `ngDoBootstrap` method. - -``` js -import { BrowserModule } from '@angular/platform-browser'; -import { NgModule, Injector } from '@angular/core'; -import { createCustomElement } from '@angular/elements'; -import { AppComponent } from './app.component'; -import { ReactiveFormsModule } from '@angular/forms'; - -@NgModule({ - declarations: [ - AppComponent - ], - imports: [ - BrowserModule, - ReactiveFormsModule - ], - providers: [], - entryComponents: [AppComponent] -}) -export class AppModule { - constructor(private injector: Injector) {} - - ngDoBootstrap() { - const el = createCustomElement(AppComponent, { injector: this.injector }); - customElements.define('angular-publisher-widget', el); - } -} -``` - -#### Create Custom Event - -Replace the contents of `angular-publisher-widget/src/app/app.component.ts`. - -- Here, we're adding code to dispatch the custom event. - -``` js -import { Component } from '@angular/core'; -import { FormControl, FormGroup } from '@angular/forms'; - -const EVENTS = { - greeting: 'greeting', -}; - -@Component({ - selector: 'app-root', - templateUrl: './app.component.html', - styleUrls: ['./app.component.css'] -}) -export class AppComponent { - greetingForm = new FormGroup({ - name: new FormControl(''), - }); - - publishWidgetEvent(eventId, detail) { - const widgetEvent = new CustomEvent(eventId, { detail }); - window.dispatchEvent(widgetEvent); - } - - onSubmit() { - const name = this.greetingForm.get('name').value; - this.publishWidgetEvent(EVENTS.greeting, { name }); - } -} -``` - -#### Add HTML Form - -Replace the contents of `angular-publisher-widget/src/app/app.component.html`. - -- In the app component html, we're adding a simple form to call our component class `app.component.ts`. - -``` html -

Send a greeting

-
- - -
-``` -#### View Micro Frontend - -Open `angular-publisher-widget/src/index.html`. - -In the ``, replace `` with your custom element ``. - -``` html - - - -``` - -You can check to see if your micro frontend is working in your browser (e.g., localhost:4200) - -### Add to App Builder - -Now we're ready to host our micro frontend in Entando. - -#### Build It - -From the project root, type: - -``` bash -ng build --prod --outputHashing=none -``` - -This will generate a `dist` directory. - -#### Create Public Folder - -1. Navigate to `Entando App Builder` in your browser. - -2. Click `Configuration` → `File Browser` → `public`. - -3. Create a folder named `angular-publisher-widget`. - -3. Click `Upload Files`. - -4. From your generated `dist` folder, upload: - -- `main-es2015.js` -- `polyfills-es2015.js` -- `runtime-es2015.js` - -#### Add Widget - -1. Go to `Components > Micro frontends & Widgets` in the Entando App Builder. - -2. Click `Add` at the lower right. - -3. Enter the following: - -- `Code: angular_publisher_widget` → note: dashes are not allowed -- `Title: Angular Publisher Widget` → for both English and Italian languages -- `Group: Free Access` -- `Custom UI:` - -``` ftl -<#assign wp=JspTaglibs[ "/aps-core"]> - - - - - -``` - -4. Click `Save`. - -#### View on Homepage - -1. Go to `Pages` → `Management` - -2. Next to the `Home` page `(folder icon)`, in the `Actions` column, click the `⋮` icon - -3. In the Search field in right-hand sidebar, enter `Angular Publisher Widget`. - -4. Drag and drop `Angular Publisher Widget` into the `Sample Frame` in the main body of the page. - -> Replace `Publisher Widget`. - -5. Click `Publish`. - -6. In the top navigation, on the right, click `Go to Homepage`. - -7. Enter a greeting in the input field. Press the submit button. The subscriber widget will update with the greeting. Done! - -- Note: If you don't see an input field, refresh the page. - -::: tip Congratulations! -You've now created an Angular micro frontend that can communicate with a React micro frontend. -::: From c05e48ec78edc71aaa2ea54a6b7e7bce4e797996 Mon Sep 17 00:00:00 2001 From: Lydia Pedersen Date: Wed, 21 Sep 2022 18:24:11 -0700 Subject: [PATCH 2/3] ENDOC-507 Update the communication tutorial --- .../tutorials/create/mfe/communication.md | 308 ++++++++++-------- 1 file changed, 176 insertions(+), 132 deletions(-) diff --git a/vuepress/docs/next/tutorials/create/mfe/communication.md b/vuepress/docs/next/tutorials/create/mfe/communication.md index 4f78544de7..4fc6278ac2 100644 --- a/vuepress/docs/next/tutorials/create/mfe/communication.md +++ b/vuepress/docs/next/tutorials/create/mfe/communication.md @@ -14,96 +14,117 @@ Entando supports communication between micro frontends (MFEs) using [Custom Even - A React MFE that listens to an event ## Prerequisites -- 2 simple React apps: One will be modified to publish an event while the other will be modified to subscribe to an event. Refer to the [simple React app tutorial](react.md#create-a-react-app-in-an-entando-bundle) to create an MFE and import and test the custom element. +- 2 [simple React apps](react.md#create-a-react-app-in-an-entando-bundle): One will be modified to publish an event while the other will be modified to subscribe to an event ## Modify the Publisher MFE +### Create Custom Event + 1. To add a custom event, create the file `publisher-widget/src/PublisherWidgetElement.js`: - ``` js - import React from 'react'; - import ReactDOM from 'react-dom'; - import App from './App'; +``` js +import React from 'react'; +import ReactDOM from 'react-dom'; +import App from './App'; - const EVENTS = { - greeting: 'greeting', - }; +const EVENTS = { + greeting: 'greeting', +}; - class PublisherWidgetElement extends HTMLElement { +class PublisherWidgetElement extends HTMLElement { - constructor() { - super(); - this.onGreet = name => this.publishWidgetEvent(EVENTS.greeting, { name }); - } + constructor() { + super(); + this.onGreet = name => this.publishWidgetEvent(EVENTS.greeting, { name }); + } - connectedCallback() { - this.mountPoint = document.createElement('div'); - this.appendChild(this.mountPoint); - this.render(); - } + connectedCallback() { + this.mountPoint = document.createElement('div'); + this.appendChild(this.mountPoint); + this.render(); + } - publishWidgetEvent(eventId, detail) { - const widgetEvent = new CustomEvent(eventId, { detail }); - window.dispatchEvent(widgetEvent); - } + publishWidgetEvent(eventId, detail) { + const widgetEvent = new CustomEvent(eventId, { detail }); + window.dispatchEvent(widgetEvent); + } - render() { - ReactDOM.render(, this.mountPoint); - } - } + render() { + ReactDOM.render(, this.mountPoint); + } +} - customElements.define('publisher-widget', PublisherWidgetElement); +customElements.define('publisher-widget', PublisherWidgetElement); - export default PublisherWidgetElement; - ``` +export default PublisherWidgetElement; +``` In the `CustomEvent` constructor, `detail` denotes the specific name to use in the event payload per the [DOM specification](https://dom.spec.whatwg.org/#interface-customevent). -2. Update `publisher-widget/src/App.js` to dispatch an event: +2. To import the custom element, update `publisher-widget/src/index.js`: + +``` js +import './index.css'; +import './PublisherWidgetElement'; +``` + +3. To test the MFE, update `publisher-widget/public/index.html` and view the app in the browser: + +``` js + + + + ... + +``` + +### Dispatch Custom Event - ``` js - import React from 'react'; - import './App.css'; +1. Update `publisher-widget/src/App.js` to dispatch an event: + +``` js +import React from 'react'; +import './App.css'; - class App extends React.Component { - constructor(props) { - super(props); - this.state = { name: ''}; - } - - handleNameChange(value) { - this.setState(prevState => ({ - ...prevState, - name: value, - })); - } - - render() { - const { name } = this.state; - const { onGreet } = this.props; - return ( -
-

Send a greeting

- - this.handleNameChange(e.target.value)} value={name} /> - -
- ); - } - } - - export default App; - ``` - -3. Enter the following in the JavaScript console of your browser: - - ``` js - window.addEventListener('greeting', (evt) => console.log('Hello', evt.detail.name)) - ``` - -4. To test the event dispatcher, write something in the text field and click the "Say hello!" button - -5. Confirm the event message appears in the JS console +class App extends React.Component { + constructor(props) { + super(props); + this.state = { name: ''}; + } + + handleNameChange(value) { + this.setState(prevState => ({ + ...prevState, + name: value, + })); + } + + render() { + const { name } = this.state; + const { onGreet } = this.props; + return ( +
+

Send a greeting

+ + this.handleNameChange(e.target.value)} value={name} /> + +
+ ); + } +} + +export default App; +``` + +2. In the JavaScript console of your browser, enter the following: + +``` js +window.addEventListener('greeting', (evt) => console.log('Hello', evt.detail.name)) +``` + +3. To test the event dispatcher, write something in the text field and click the "Say hello!" button + +4. Confirm the event message appears in the JS console ::: tip Congratulations! You’ve now published a custom event @@ -111,75 +132,98 @@ You’ve now published a custom event ## Modify the Subscriber MFE +### Create Event Listener + 1. To add an event listener, create the file `subscriber-widget/src/SubscriberWidgetElement.js`: - ``` js - import React from 'react'; - import ReactDOM from 'react-dom'; - import App from './App'; +``` js +import React from 'react'; +import ReactDOM from 'react-dom'; +import App from './App'; + +const EVENTS = { + greeting: 'greeting', +}; + +class SubscriberWidgetElement extends HTMLElement { + + constructor() { + super(); + this.name = null; + this.subscribeToWidgetEvent(EVENTS.greeting, (evt) => this.onGreeting(evt.detail.name)); + } + + connectedCallback() { + this.mountPoint = document.createElement('div'); + this.appendChild(this.mountPoint); + this.render(); + } + + subscribeToWidgetEvent(eventType, eventHandler) { + window.addEventListener(eventType, eventHandler); + } + + onGreeting(name) { + this.name = name; + this.render(); + } - const EVENTS = { - greeting: 'greeting', - }; + render() { + ReactDOM.render(, this.mountPoint); + } +} - class SubscriberWidgetElement extends HTMLElement { +customElements.define('subscriber-widget', SubscriberWidgetElement); - constructor() { - super(); - this.name = null; - this.subscribeToWidgetEvent(EVENTS.greeting, (evt) => this.onGreeting(evt.detail.name)); - } +export default SubscriberWidgetElement; +``` - connectedCallback() { - this.mountPoint = document.createElement('div'); - this.appendChild(this.mountPoint); - this.render(); - } +2. To import the custom element, update `subscriber-widget/src/index.js`: - subscribeToWidgetEvent(eventType, eventHandler) { - window.addEventListener(eventType, eventHandler); - } +``` js +import './index.css'; +import './SubscriberWidgetElement'; +``` - onGreeting(name) { - this.name = name; - this.render(); - } - render() { - ReactDOM.render(, this.mountPoint); - } - } +3. To test the MFE, update `subscriber-widget/public/index.html` and view the app in the browser: - customElements.define('subscriber-widget', SubscriberWidgetElement); +``` js + + + + ... + +``` - export default SubscriberWidgetElement; - ``` -2. Update `subscriber-widget/src/App.js` to display the custom event: +### Display Custom Event - ``` js - import React from 'react'; - import './App.css'; +1. Update `subscriber-widget/src/App.js` to display the event: - function App({ name }) { - return name ? (

Just got a greeting from {name}

) - : (

Waiting for a greeting...

); - } +``` js +import React from 'react'; +import './App.css'; - export default App; - ``` +function App({ name }) { + return name ? (

Just got a greeting from {name}

) + : (

Waiting for a greeting...

); +} -3. To test the event listener, enter the following in the JavaScript console of your browser: +export default App; +``` - ``` js - const widgetEvent = new CustomEvent('greeting', { - detail: { - name: 'Pippo' - }, - }); - window.dispatchEvent(widgetEvent); - ``` +2. To test the event listener, enter the following in the JavaScript console of your browser: -4. Confirm the custom event is displayed in the `subscriber-widget` +``` js +const widgetEvent = new CustomEvent('greeting', { + detail: { + name: 'Pippo' + }, +}); +window.dispatchEvent(widgetEvent); +``` + +3. Confirm the custom event is displayed in the `subscriber-widget` ::: tip Congratulations! You’ve now created a micro frontend that listens to custom events @@ -189,7 +233,7 @@ You’ve now created a micro frontend that listens to custom events To add the publisher and subscriber MFEs to Entando, run the following commands from the root folder of each: -``` sh +``` ent bundle pack ent bundle publish ent bundle deploy @@ -204,26 +248,26 @@ Set up the widgets on an existing page or [create your own page](../../compose/p 1. Go to `Pages` → `Management` -2. For the `Home` page `(folder icon)`, in the `Actions` column, click the `⋮` icon +2. On the line item for the `Home` page, in the `Actions` column, click the `⋮` icon 3. Click `Edit` 4. In the `Settings` section, select a Page Template with more than one frame -5. Click `Save and Configure` +5. Click `Save and Design` -6. From the `WIDGETS` sidebar on the right, drag `Publisher Widget` and `Subscriber Widget` into `Frame 1` and `Frame 2` +6. From the `Widgets` tab in the right sidebar, drag your publisher and subscriber widgets into `Frame 1` and `Frame 2` 7. Click `Publish` -8. To view the `Home` page, scroll up and click `Go to Homepage` +8. To view the `Home` page, scroll up and click `View Published Page` -9. Enter a greeting in the input field and click the submit button +9. Enter a name in the input field and click the "Say hello!" button -10. Confirm that the subscriber widget updates to display the greeting +10. Confirm that the subscriber widget updates to display the name ::: tip Congratulations! -You can now communicate between micro frontends with `Custom Events` +You can now communicate between micro frontends using custom events! ::: From c9640c3c738a372cf84f3be94e52e819a76d0f8a Mon Sep 17 00:00:00 2001 From: Lydia Pedersen Date: Thu, 22 Sep 2022 16:18:37 -0700 Subject: [PATCH 3/3] ENDOC-507 Apply PR feedback --- .../tutorials/create/mfe/communication.md | 26 +++++++++++-------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/vuepress/docs/next/tutorials/create/mfe/communication.md b/vuepress/docs/next/tutorials/create/mfe/communication.md index 4fc6278ac2..af4ef8dc8d 100644 --- a/vuepress/docs/next/tutorials/create/mfe/communication.md +++ b/vuepress/docs/next/tutorials/create/mfe/communication.md @@ -18,7 +18,7 @@ Entando supports communication between micro frontends (MFEs) using [Custom Even ## Modify the Publisher MFE -### Create Custom Event +### Create the Custom Event 1. To add a custom event, create the file `publisher-widget/src/PublisherWidgetElement.js`: @@ -61,14 +61,14 @@ export default PublisherWidgetElement; In the `CustomEvent` constructor, `detail` denotes the specific name to use in the event payload per the [DOM specification](https://dom.spec.whatwg.org/#interface-customevent). -2. To import the custom element, update `publisher-widget/src/index.js`: +2. To import the custom element, replace the contents of `publisher-widget/src/index.js`: ``` js import './index.css'; import './PublisherWidgetElement'; ``` -3. To test the MFE, update `publisher-widget/public/index.html` and view the app in the browser: +3. To test the MFE, update the `body` section of `publisher-widget/public/index.html`: ``` js @@ -78,9 +78,11 @@ import './PublisherWidgetElement'; ``` -### Dispatch Custom Event +4. Confirm the app renders in the browser -1. Update `publisher-widget/src/App.js` to dispatch an event: +### Dispatch the Custom Event + +1. Replace the contents of `publisher-widget/src/App.js`: ``` js import React from 'react'; @@ -132,7 +134,7 @@ You’ve now published a custom event ## Modify the Subscriber MFE -### Create Event Listener +### Create the Event Listener 1. To add an event listener, create the file `subscriber-widget/src/SubscriberWidgetElement.js`: @@ -178,7 +180,7 @@ customElements.define('subscriber-widget', SubscriberWidgetElement); export default SubscriberWidgetElement; ``` -2. To import the custom element, update `subscriber-widget/src/index.js`: +2. To import the custom element, replace the contents of `subscriber-widget/src/index.js`: ``` js import './index.css'; @@ -186,7 +188,7 @@ import './SubscriberWidgetElement'; ``` -3. To test the MFE, update `subscriber-widget/public/index.html` and view the app in the browser: +3. To test the MFE, update the `body` section of `subscriber-widget/public/index.html`: ``` js @@ -196,9 +198,11 @@ import './SubscriberWidgetElement'; ``` -### Display Custom Event +4. Confirm the app renders in the browser + +### Display the Custom Event -1. Update `subscriber-widget/src/App.js` to display the event: +1. Replace the contents of `subscriber-widget/src/App.js`: ``` js import React from 'react'; @@ -244,7 +248,7 @@ Refer to the tutorial on how to [publish a bundle project](../pb/publish-project ### View on a Page -Set up the widgets on an existing page or [create your own page](../../compose/page-management.md). The following steps assume you'll use the `Home` page. +Place the widgets on an existing page or [create your own page](../../compose/page-management.md). The following steps assume you'll edit the `Home` page. 1. Go to `Pages` → `Management`