Layout Container
<bk-layout-container></bk-layout-container>
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:
- re-using
back-kit
components without letting functionalities (mostly clients') trump each other - render multiple layouts together like a page with table, then a card detail, then another table and so on
- 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.
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
property | attribute | type | default | description |
---|---|---|---|---|
content | - | Content | - | layouts configuration |
disableShadowDom | disable-shadow-dom | boolean | false | disable the shadow dom as render root (only use as empty attribute) |
currentLayout | current-layout | string | - | 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
event | action |
---|---|
layout/change | requires the connection of the layout which is referenced in the event payload |
Emits
None