Skip to main content
Version: 13.x (Current)

Layout Container

<bk-layout-container></bk-layout-container>
caution

Using @micro-lc/composer@^2 and @micro-lc/orchestrator@^2 as rendering engine and micro-frontend orchestrator, the Layout Swap should be used instead of the Layout Container.

This component is meant to allow multiple configurations to live within the same plugin by:

  1. re-using back-kit components without letting functionalities (mostly clients') trump each other
  2. render multiple layouts together like a page with table, then a card detail, then another table and so on
  3. condensate plugins into a single one

A simple instance would be a user which might want to explore multiple details connected with its user but persisted on different entities.

Since a backend resource, like a database collection/table, is mostly mapped 1:1 on a Microfrontend Composer plugin using a single client, like the CRUD Client, it is recommendable to use different plugins to render different collections. For those cases falling outside the previous scope a layout that can be switched might come in handy.

By reproducing an element-composer-compatible configuration, the Layout Container provides a wrapper for different configurations wired to one or many event-bus instances. Such configurations are switched whenever the Layout Container receives to the request of switching to a new layout, via a layout/change event.

How to configure

The Layout Container should be provided with the content property, specifying the configurations of the layouts to orchestrate.

{
"tag": "bk-layout-container",
"properties": {
"content": {
"$default": {
... // first plugin
},
"currentBasket": {
... // second plugin
}
}
}
}

The $default key is not mandatory but is reserved and marks the layout to render on landing. The Layout Container also allows to specify the default layout through property currentLayout.

Event bus

Each layout has a dedicated EventBus instance which has the same name of the configuration key. This is by default injected to all components of the layout.

To configure this behavior the key busDiscriminator is available.

This defaults to $inherit and takes the EventBus of its parent. Specifying a different value spawns a new EventBus.

Disable shadow dom

Adding the attribute disable-shadow-dom allows to disable the shadow dom for the Layout Container, which can be useful when it has to embed children which bubble events up to the document root such as the Calendar.

caution

disable-shadow-dom needs be passed as an empty attribute to the Layout Container, and not as property. For instance:

{
"tag": "bk-layout-container",
"attributes": {
"disable-shadow-dom":""
},
"properties": {
"content": {
"$default": {
... // first plugin
},
"currentBasket": {
... // second plugin
}
}
}
}

Examples

Example: Merging two plugins into one

Let's then suppose we have a customer, a list of their previous purchases and a list of their current basket items.

We could use different plugins. For previous purchases it would look like:

// previous-purchases.json
{
"$ref": {
"ppSchema": {
"type": "object",
"properties": {
"_id": {"type": "string"},
"items": {"type": "array"}
}
}
},
"content": {
"type": "row",
"content": [
{
"tag": "bk-table",
"properties": {
"dataSchema": {"$ref": "ppSchema"}
}
},
{
"tag": "bk-crud-client",
"properties": {
"dataSchema": {"$ref": "ppSchema"}
}
}
]
}
}

while current basket would look like:

// current-basket.json
{
"$ref": {
"cbSchema": {
"type": "object",
"properties": {
"_id": {"type": "string"},
"description": {"type": "string"},
"price": {"type": "number"}
}
}
},
"content": {
"type": "row",
"content": [
{
"tag": "bk-table",
"properties": {
"dataSchema": {"$ref": "cbSchema"}
}
},
{
"tag": "bk-crud-client",
"properties": {
"dataSchema": {"$ref": "cbSchema"}
}
}
]
}
}

If the UI should instead include two tables in a page that can be visually swapped by a set of buttons or tabs, wrapping both configurations in the Layout Container does the job.

// single-plugin.json
{
"$ref": {
"ppSchema": {
"type": "object",
"properties": {
"_id": {"type": "string"},
"items": {"type": "array"}
}
},
"cbSchema": {
"type": "object",
"properties": {
"_id": {"type": "string"},
"description": {"type": "string"},
"price": {"type": "number"}
}
}
},
"content": {
"tag": "bk-layout-container",
"properties": {
"content": {
"$default": {/* first plugin */},
"currentBasket": {/* second plugin */}
}
}
}
}

Example: switch layout using a button

The Button can be used to switch to a different layout:

{
"tag": "bk-button",
"properties": {
"content": "View Orders",
"action": {
"type": "event",
"config": {
"label": "layout/change",
"payload": {
"layout": "orders"
}
}
}
}
},
{
"tag": "bk-button",
"properties": {
"content": "View Riders",
"action": {
"type": "event",
"config": {
"label": "layout/change",
"payload": {
"layout": "riders"
}
}
}
}
},
{
"tag": "bk-layout-container",
"properties": {
"content": {
"riders": {...},
"orders": {...}
}
}
}

Example: switch layout using tabs

The Tabs can be used to navigate between layouts:

{
"tag": "bk-tabs",
"properties": {
"tabs": [
{
"key": "riders",
"title": "Riders",
"event": {
"label": "layout/change",
"payload": {
"layout": "riders"
}
}
},
{
"key": "customers",
"title": "Customers",
"event": {
"label": "layout/change",
"payload": {
"layout": "customers"
}
}
}
]
}
},
{
"tag": "bk-layout-container",
"properties": {
"content": {
"riders": {...},
"orders": {...}
}
}
}

API

Properties & Attributes

propertyattributetypedefaultdescription
content-Content-layouts configuration
disableShadowDomdisable-shadow-dombooleanfalsedisable the shadow dom as render root (only use as empty attribute)
currentLayoutcurrent-layoutstring-default layout to view on landing

Content

type Content = Record<string, LayoutNode> | Record<string, LayoutNode[]>
type LayoutNode = {
attributes?: Record<string, string>
busDiscriminator?: string | string[]
content?: LayoutNode | LayoutNode[]
properties?: Record<string, any>
tag?: string
type?: string
}

Listens to

eventaction
layout/changerequires the connection of the layout which is referenced in the event payload

Emits

None