Web component that allows embedding web content using the OutletRouter. The content is displayed inside an iframe to achieve the highest possible level of isolation between the microfrontends via a separate browsing context.

To embed a microfrontend, place this custom HMTL element <sci-router-outlet></sci-router-outlet> in an HTML template, give it a name via its name attribute and navigate via OutletRouter to instruct the outlet to load the microfrontend.

  1. Place the web component in an HTML template:
<sci-router-outlet name="detail"></sci-router-outlet>
  1. Control the outlet's content:
Beans.get(OutletRouter).navigate('https://micro-frontends.org', {outlet: 'detail'});

Outlets can be nested, allowing a microfrontend to embed another microfrontend. There is no limit to the number of nested outlets. However, be aware that nested content is loaded cascaded, that is, only loaded once its parent content finished loading.

When adding the outlet to the DOM, the outlet displays the last URL routed for it, if any. When repeating routing for an outlet, its content is replaced.


Outlet Context

The router outlet allows associating contextual data, which then is available to embedded content at any nesting level. Data must be serializable with the structured clone algorithm. Embedded content can look up contextual data using the ContextService. Typically, contextual data is used to provide microfrontends with information about their embedding environment. Looking up contextual data requires the embedded microfrontend to be a registered micro application.

Each outlet spans a new context. A context is like a Map with key-value entries. Contexts form a hierarchical tree structure. When looking up a value and if the value is not found in the current context, the lookup is retried on the parent context, repeating until either a value is found, or the root of the context tree has been reached.

You can set contextual data as following:

 const outlet: SciRouterOutletElement = document.querySelector('sci-router-outlet');
outlet.setContextValue('key', 'value');

Embedded content can look up contextual data as following:

Beans.get(ContextService).observe$('key').subscribe(value => {
...
});

Outlet size

The router outlet can adapt its size to the preferred size of its embedded content. The preferred size is set by the microfrontend embedded in the router outlet, which, therefore, requires the embedded microfrontend to be connected to the platform.

Embedded content can report its preferred size using the PreferredSizeService, causing the outlet to adapt its size.

Keystroke Bubbling

The router outlet allows the registration of keystrokes, instructing embedded content at any nesting level to propagate corresponding keyboard events to this outlet. The outlet dispatches keyboard events for registered keystrokes as synthetic keyboard events via its event dispatcher. They bubble up the DOM tree like regular events. Propagated events are of the original type, meaning that when the user presses a key on the keyboard, a keydown keyboard event is dispatched, or a keyup event when releasing a key, respectively. Keystroke bubbling requires the embedded microfrontend to be a registered micro application.

A keystroke is a string that has several parts, each separated with a dot. The first part specifies the event type (keydown or keyup), followed by optional modifier part(s) (alt, shift, control, meta, or a combination thereof) and with the keyboard key as the last part. The key is a case-insensitive value of the KeyboardEvent.key property. Two keys are an exception to the value of the KeyboardEvent.key property: dot and space. For a complete list of valid key values, see https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key/Key_Values.

You can register keystrokes via the keystrokes attribute in the HTML template, or via the keystrokes property on the DOM element. If setting keystrokes via the HTML template, multiple keystrokes are separated by a comma.

If you want to prevent the default action of a keystroke, add the preventDefault flag. If not specifying the flag, the default action won't be prevented.

HTML template:

<sci-router-outlet keystrokes="keydown.control.alt.enter{preventDefault=true},keydown.escape,keydown.control.space"></sci-router-outlet>

Alternatively, you can register keystrokes on the DOM element as shown below.

TypeScript:

 const outlet: SciRouterOutletElement = document.querySelector('sci-router-outlet');
outlet.keystrokes = [
'keydown.control.alt.enter{preventDefault=true}',
'keydown.escape',
'keydown.control.space'
];

Scrollable Content

By default, page scrolling is enabled for the embedded content, displaying a scrollbar when it overflows. If disabled, overflowing content is clipped, unless the embedded content uses a viewport, or reports its preferred size to the outlet.

The below code snippet illustrates how to disable page scrolling for the embedded content.

<sci-router-outlet scrollable="false"></sci-router-outlet>

Router Outlet Events

The router outlet emits the following events as custom DOM events. You can attach an event listener declaratively in the HTML template using the onevent handler syntax, or programmatically using the addEventListener method.

  • activate The activate custom DOM event is fired when a microfrontend is mounted. It contains the URL of the mounted microfrontend in its details property as string value. The microfrontend may not be fully loaded yet.

  • deactivate The deactivate custom DOM event is fired when a microfrontend is about to be unmounted. It contains the URL of the unmounted microfrontend in its details property as string value.

  • focuswithin The focuswithin custom DOM event is fired when the microfrontend loaded into the outlet, or any of its child microfrontends, has gained or lost focus. It contains the current focus-within state in its details property as a boolean value: true if focus was gained, or false if focus was lost. The event does not bubble up through the DOM. After gaining focus, the event is not triggered again until embedded content loses focus completely, i.e., when focus does not remain in the embedded content at any nesting level. This event behaves like the :focus-within CSS pseudo-class but operates across iframe boundaries. For example, it can be useful when implementing overlays that close upon focus loss.

    Note that SCION can only monitor microfrontends of registered micro apps that are connected to the platform.

Usage:

<sci-router-outlet onfocuswithin="onFocusWithin()"></sci-router-outlet>

For an Angular application, it would look as follows:

<sci-router-outlet (focuswithin)="onFocusWithin($event)"></sci-router-outlet>

Splash

Loading and bootstrapping a microfrontend can take some time, at worst, only displaying content once initialized.

To indicate the loading of a microfrontend, the navigator can instruct the router outlet to display a splash until the microfrontend signals readiness.

Beans.get(OutletRouter).navigate('path/to/microfrontend', {showSplash: true});

The splash is the markup between the opening and closing tags of the router outlet element.

<sci-router-outlet>
Loading...
</sci-router-outlet>

The splash is displayed until the embedded microfrontend signals readiness.

MicrofrontendPlatformClient.signalReady();

Layouting the Splash

To lay out the content of the splash use the pseudo-element selector ::part(splash).

Example of centering splash content in a CSS grid container:

sci-router-outlet::part(splash) {
display: grid;
place-content: center;
}

Web component

The outlet is registered as a custom element in the browser's custom element registry as defined by the Web Components standard. See https://developer.mozilla.org/en-US/docs/Web/Web_Components for more information.

Miscellaneous

If no content is routed for display in the router outlet, the CSS class sci-empty is added to the outlet. An outlet will not display content if either there has not yet been any navigation for the outlet or the outlet content has been cleared.

Hierarchy

  • HTMLElement
    • SciRouterOutletElement

Constructors

Properties

empty$: Observable<boolean>

Emits whether content is routed for display in this router outlet. Upon subscription, the Observable emits the current empty state, and then continuously emits when it changes. It never completes.

An outlet does not display content if no navigation has taken place yet, or if the outlet content has been cleared.

Accessors

  • get contextValues$(): Observable<Map<string, any>>
  • Returns an Observable that emits the context of this outlet. Context values inherited from parent contexts are not returned. The Observable never completes, and emits when a context value is added to or removed from the outlet context.

    Returns Observable<Map<string, any>>

  • get keystrokes(): string[]
  • Returns the keystrokes which to bubble across the iframe boundaries.

    Returns string[]

  • set keystrokes(keystrokes): void
  • Instructs embedded content at any nesting level to propagate keyboard events to this outlet. The outlet dispatches keyboard events for registered keystrokes as synthetic keyboard events via its event dispatcher. They bubble up the DOM tree like regular events. Propagated events are of the original type, meaning that when the user presses a key on the keyboard, a keydown keyboard event is dispatched, or a keyup event when releasing a key, respectively.

    Parameters

    • keystrokes: string[]

      A keystroke is specified as a string that has several parts, each separated with a dot. The first part specifies the event type (keydown or keyup), followed by optional modifier part(s) (alt, shift, control, meta, or a combination thereof) and with the keyboard key as the last part. The key is a case-insensitive value of the KeyboardEvent#key property. For a complete list of valid key values, see https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key/Key_Values. Two keys are an exception to the value of the KeyboardEvent#key property: dot and space.
      To prevent the default action of a keystroke, the preventDefault flag can be added.
      Examples: keydown.control.z{preventDefault=true}, keydown.escape, keyup.enter, keydown.control.alt.enter, keydown.control.space.

    Returns void

  • get scrollable(): boolean
  • Returns whether the embedded document is natively page scrollable.

    Returns boolean

  • set scrollable(scrollable): void
  • Specifies whether to enable or disable native page scrolling in the embedded document.

    By default, page scrolling is enabled for the embedded content, displaying a scrollbar when it overflows. If disabled, overflowing content is clipped, unless the embedded content uses a viewport, or reports its preferred size to the outlet.

    Parameters

    • scrollable: boolean

    Returns void

Methods

  • Removes data registered under the given key from the context.

    Removal does not affect parent contexts, so it is possible that a subsequent call to ContextService.observe$ with the same name will return a non-null result, due to a value being stored in a parent context.

    Parameters

    • name: string

    Returns boolean

    true if removed the value from the outlet context; otherwise false.

  • Makes contextual data available to embedded content. Embedded content can lookup contextual data using the ContextService. Contextual data must be serializable with the structured clone algorithm.

    Type Parameters

    • T = any

    Parameters

    • name: string
    • value: T

    Returns void

Generated using TypeDoc