@genesislcap/foundation-layout 9.0.1-alpha-b5c5eb7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +916 -0
- package/dist/1.0.0.remoteEntry.js +1 -0
- package/dist/191.191.106ece7a41ded6731029.js +2 -0
- package/dist/191.9a61143c2afb6057ad1bae886d5d1a6e.js.map +1 -0
- package/dist/259.09c601e5288d875caab4df1e2354c0ea.js.map +1 -0
- package/dist/259.259.216fcad43e9a38888e08.js +2 -0
- package/dist/415.415.094780a1a1162c7e5f1c.js +3 -0
- package/dist/415.415.094780a1a1162c7e5f1c.js.LICENSE.txt +4 -0
- package/dist/415.fcfb4f02eaecbfa31fc322639f244245.js.map +1 -0
- package/dist/459.459.c9f0bb440eb1f041c99e.js +515 -0
- package/dist/459.cb5f5b49b4e8881992c420f3b1ca863d.js.map +1 -0
- package/dist/623.623.0e7e8f23454ee96ed9c8.js +3 -0
- package/dist/623.623.0e7e8f23454ee96ed9c8.js.LICENSE.txt +4 -0
- package/dist/623.e8f211473f9034c4157d362efb017821.js.map +1 -0
- package/dist/755.718e14af7194fb741f98580b24b2bb8f.js.map +1 -0
- package/dist/755.755.f93ee58c2b836a669ec4.js +2 -0
- package/dist/dashboard.json +1 -0
- package/dist/dts/index.d.ts +3 -0
- package/dist/dts/index.d.ts.map +1 -0
- package/dist/dts/index.federated.d.ts +1 -0
- package/dist/dts/index.federated.d.ts.map +1 -0
- package/dist/dts/main/index.d.ts +6 -0
- package/dist/dts/main/index.d.ts.map +1 -0
- package/dist/dts/main/layout-components.d.ts +42 -0
- package/dist/dts/main/layout-components.d.ts.map +1 -0
- package/dist/dts/main/layout-item.d.ts +70 -0
- package/dist/dts/main/layout-item.d.ts.map +1 -0
- package/dist/dts/main/layout-main.d.ts +186 -0
- package/dist/dts/main/layout-main.d.ts.map +1 -0
- package/dist/dts/main/layout-region.d.ts +70 -0
- package/dist/dts/main/layout-region.d.ts.map +1 -0
- package/dist/dts/styles/constants.d.ts +7 -0
- package/dist/dts/styles/constants.d.ts.map +1 -0
- package/dist/dts/styles/dragging.styles.d.ts +7 -0
- package/dist/dts/styles/dragging.styles.d.ts.map +1 -0
- package/dist/dts/styles/index.d.ts +4 -0
- package/dist/dts/styles/index.d.ts.map +1 -0
- package/dist/dts/styles/layout.styles.d.ts +8 -0
- package/dist/dts/styles/layout.styles.d.ts.map +1 -0
- package/dist/dts/utils/constants.d.ts +14 -0
- package/dist/dts/utils/constants.d.ts.map +1 -0
- package/dist/dts/utils/error.d.ts +13 -0
- package/dist/dts/utils/error.d.ts.map +1 -0
- package/dist/dts/utils/events.d.ts +38 -0
- package/dist/dts/utils/events.d.ts.map +1 -0
- package/dist/dts/utils/index.d.ts +7 -0
- package/dist/dts/utils/index.d.ts.map +1 -0
- package/dist/dts/utils/logger.d.ts +2 -0
- package/dist/dts/utils/logger.d.ts.map +1 -0
- package/dist/dts/utils/misc.d.ts +10 -0
- package/dist/dts/utils/misc.d.ts.map +1 -0
- package/dist/dts/utils/templates.d.ts +6 -0
- package/dist/dts/utils/templates.d.ts.map +1 -0
- package/dist/dts/utils/types.d.ts +63 -0
- package/dist/dts/utils/types.d.ts.map +1 -0
- package/dist/esm/index.federated.js +2 -0
- package/dist/esm/index.federated.js.map +1 -0
- package/dist/esm/index.js +3 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/main/index.js +6 -0
- package/dist/esm/main/index.js.map +1 -0
- package/dist/esm/main/layout-components.js +36 -0
- package/dist/esm/main/layout-components.js.map +1 -0
- package/dist/esm/main/layout-item.js +86 -0
- package/dist/esm/main/layout-item.js.map +1 -0
- package/dist/esm/main/layout-main.js +391 -0
- package/dist/esm/main/layout-main.js.map +1 -0
- package/dist/esm/main/layout-region.js +98 -0
- package/dist/esm/main/layout-region.js.map +1 -0
- package/dist/esm/main/main.css +17 -0
- package/dist/esm/styles/constants.js +16 -0
- package/dist/esm/styles/constants.js.map +1 -0
- package/dist/esm/styles/dragging.styles.js +116 -0
- package/dist/esm/styles/dragging.styles.js.map +1 -0
- package/dist/esm/styles/index.js +4 -0
- package/dist/esm/styles/index.js.map +1 -0
- package/dist/esm/styles/layout.styles.js +530 -0
- package/dist/esm/styles/layout.styles.js.map +1 -0
- package/dist/esm/utils/constants.js +14 -0
- package/dist/esm/utils/constants.js.map +1 -0
- package/dist/esm/utils/error.js +17 -0
- package/dist/esm/utils/error.js.map +1 -0
- package/dist/esm/utils/events.js +26 -0
- package/dist/esm/utils/events.js.map +1 -0
- package/dist/esm/utils/index.js +7 -0
- package/dist/esm/utils/index.js.map +1 -0
- package/dist/esm/utils/logger.js +3 -0
- package/dist/esm/utils/logger.js.map +1 -0
- package/dist/esm/utils/misc.js +24 -0
- package/dist/esm/utils/misc.js.map +1 -0
- package/dist/esm/utils/templates.js +11 -0
- package/dist/esm/utils/templates.js.map +1 -0
- package/dist/esm/utils/types.js +4 -0
- package/dist/esm/utils/types.js.map +1 -0
- package/dist/favicon.ico +0 -0
- package/dist/foundation-layout.api.json +1574 -0
- package/dist/foundation-layout.d.ts +478 -0
- package/dist/foundationLayout.8b94161c9f0d0d475d026a05513893c1.js.map +1 -0
- package/dist/index.ejs +23 -0
- package/dist/index.html +15 -0
- package/dist/info.ejs +13 -0
- package/dist/main.40c13c1585eb6fa5761a17ab29a7851e.js.map +1 -0
- package/dist/main.94f8a6853d484ec34632.js +2 -0
- package/dist/npm.consola.713.b1e4073e73c71572987a.js +2 -0
- package/dist/npm.consola.a0d3324d3e61dcc430c3029da5f4dcc7.js.map +1 -0
- package/dist/npm.genesis-community.248.9c9900001dbc5ba9c3ed.js +2 -0
- package/dist/npm.genesis-community.2e0cc159dabe113d6fb29bb505c1a0d4.js.map +1 -0
- package/dist/npm.microsoft.127.00f16f24d8da8fd89263.js +1469 -0
- package/dist/npm.microsoft.127.00f16f24d8da8fd89263.js.LICENSE.txt +14 -0
- package/dist/npm.microsoft.be43958facd28231e770c1307660f64d.js.map +1 -0
- package/dist/remoteEntry.js +2 -0
- package/dist/serve.json +3 -0
- package/dist/tsdoc-metadata.json +11 -0
- package/docs/.gitattributes +2 -0
- package/docs/api/foundation-layout.default_reload_buffer.md +18 -0
- package/docs/api/foundation-layout.foundationlayout.additem.md +38 -0
- package/docs/api/foundation-layout.foundationlayout.dragging.md +16 -0
- package/docs/api/foundation-layout.foundationlayout.getlayout.md +22 -0
- package/docs/api/foundation-layout.foundationlayout.layoutrequiredregistrations.md +37 -0
- package/docs/api/foundation-layout.foundationlayout.loadlayout.md +37 -0
- package/docs/api/foundation-layout.foundationlayout.md +44 -0
- package/docs/api/foundation-layout.foundationlayout.registereditems.md +26 -0
- package/docs/api/foundation-layout.foundationlayout.registeritem.md +42 -0
- package/docs/api/foundation-layout.foundationlayout.reloadbuffer.md +16 -0
- package/docs/api/foundation-layout.foundationlayoutcomponents.md +50 -0
- package/docs/api/foundation-layout.foundationlayoutitem.closable.md +16 -0
- package/docs/api/foundation-layout.foundationlayoutitem.md +35 -0
- package/docs/api/foundation-layout.foundationlayoutitem.registration.md +21 -0
- package/docs/api/foundation-layout.foundationlayoutitem.size.md +16 -0
- package/docs/api/foundation-layout.foundationlayoutitem.title.md +21 -0
- package/docs/api/foundation-layout.foundationlayoutregion.md +33 -0
- package/docs/api/foundation-layout.foundationlayoutregion.size.md +16 -0
- package/docs/api/foundation-layout.foundationlayoutregion.type.md +16 -0
- package/docs/api/foundation-layout.layoutemitevents.md +22 -0
- package/docs/api/foundation-layout.layoutreceiveevents.md +20 -0
- package/docs/api/foundation-layout.layoutreceiveeventsdetail.md +23 -0
- package/docs/api/foundation-layout.layoutregiontype.md +16 -0
- package/docs/api/foundation-layout.layoutregistrationerror._constructor_.md +23 -0
- package/docs/api/foundation-layout.layoutregistrationerror.md +23 -0
- package/docs/api/foundation-layout.layoutstyles.md +21 -0
- package/docs/api/foundation-layout.layouttemplate.md +21 -0
- package/docs/api/foundation-layout.layoutusageerror._constructor_.md +23 -0
- package/docs/api/foundation-layout.layoutusageerror.md +23 -0
- package/docs/api/foundation-layout.md +42 -0
- package/docs/api/foundation-layout.placement.md +18 -0
- package/docs/api/foundation-layout.registeredelementconfig.closable.md +14 -0
- package/docs/api/foundation-layout.registeredelementconfig.md +30 -0
- package/docs/api/foundation-layout.registeredelementconfig.registration.md +14 -0
- package/docs/api/foundation-layout.registeredelementconfig.size.md +14 -0
- package/docs/api/foundation-layout.registeredelementconfig.title.md +14 -0
- package/docs/api/foundation-layout.serialisedlayout.md +26 -0
- package/docs/api/index.md +12 -0
- package/docs/api-report.md +235 -0
- package/docs/img/foundation-layout-example.png +0 -0
- package/license.txt +46 -0
- package/package.json +80 -0
package/README.md
ADDED
|
@@ -0,0 +1,916 @@
|
|
|
1
|
+
# Genesis Foundation UI App Layout
|
|
2
|
+
|
|
3
|
+
[](https://lerna.js.org/)
|
|
4
|
+
[](https://www.typescriptlang.org/)
|
|
5
|
+
|
|
6
|
+
### [API Docs](./docs/api/index.md)
|
|
7
|
+
|
|
8
|
+
## Declarative HTML API
|
|
9
|
+
|
|
10
|
+
The following example shows the usage of the declarative API with `zero-charts` and the output that it produces.
|
|
11
|
+
```html
|
|
12
|
+
<foundation-layout>
|
|
13
|
+
<foundation-layout-region>
|
|
14
|
+
<foundation-layout-item closable title="Pie">
|
|
15
|
+
<zero-charts
|
|
16
|
+
type="rose"
|
|
17
|
+
:config=${(x) => x.roseConfig}
|
|
18
|
+
:data=${(x) => x.roseData}
|
|
19
|
+
></zero-charts>
|
|
20
|
+
</foundation-layout-item>
|
|
21
|
+
<foundation-layout-region type="vertical">
|
|
22
|
+
<foundation-layout-item title="Positions Area Chart">
|
|
23
|
+
<zero-charts type="area" :config=${(x) => x.areaConfig}>
|
|
24
|
+
<charts-datasource
|
|
25
|
+
resourceName="ALL_POSITIONS"
|
|
26
|
+
server-fields="INSTRUMENT_NAME QUANTITY"
|
|
27
|
+
charts-fields="type value"
|
|
28
|
+
isSnapshot="true"
|
|
29
|
+
></charts-datasource>
|
|
30
|
+
</zero-charts>
|
|
31
|
+
</foundation-layout-item>
|
|
32
|
+
<foundation-layout-item title="Positions Column Chart">
|
|
33
|
+
<zero-charts type="column" :config=${(x) => x.columnConfig}>
|
|
34
|
+
<charts-datasource
|
|
35
|
+
resourceName="ALL_POSITIONS"
|
|
36
|
+
server-fields="INSTRUMENT_NAME QUANTITY"
|
|
37
|
+
charts-fields="type value"
|
|
38
|
+
isSnapshot="true"
|
|
39
|
+
></charts-datasource>
|
|
40
|
+
</zero-charts>
|
|
41
|
+
</foundation-layout-item>
|
|
42
|
+
</foundation-layout-region>
|
|
43
|
+
</foundation-layout-region>
|
|
44
|
+
</foundation-layout>
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+

|
|
48
|
+
|
|
49
|
+
## Set-up
|
|
50
|
+
|
|
51
|
+
### Basic install
|
|
52
|
+
|
|
53
|
+
To enable this module in your application, follow the steps below.
|
|
54
|
+
|
|
55
|
+
1. Add `@genesislcap/foundation-layout` as a dependency in your **package.json** file. Whenever you change the dependencies of your project, ensure you run the `$ npm run bootstrap` command again.
|
|
56
|
+
|
|
57
|
+
```javascript
|
|
58
|
+
{
|
|
59
|
+
...
|
|
60
|
+
"dependencies": {
|
|
61
|
+
"@genesislcap/foundation-layout": "latest"
|
|
62
|
+
},
|
|
63
|
+
...
|
|
64
|
+
}
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
2. Register the layout with the design system. This is probably in a file called **components.ts**, located where you call `.register()` on the design system.
|
|
68
|
+
|
|
69
|
+
```javascript
|
|
70
|
+
FoundationDesignSystem: registerFoundationDesignSystem().register(
|
|
71
|
+
// ...Other registrations
|
|
72
|
+
// add foundationLayoutComponents here
|
|
73
|
+
foundationLayoutComponents,
|
|
74
|
+
)
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
- This registers the three custom elements for use in your application. The components will use the prefix of the design system as their prefix. For example, the root component will be `<foundation-layout>` in the `Foundation` design system, and `<zero-layout>` in the `Zero (alpha)` design system.
|
|
78
|
+
|
|
79
|
+
:::info
|
|
80
|
+
For the rest of this document, the components will be referred to with the `foundation-` prefix.
|
|
81
|
+
:::
|
|
82
|
+
|
|
83
|
+
### Custom styling
|
|
84
|
+
|
|
85
|
+
The required class, template, and base styles are exported as part of the package, allowing a client to customise the styling of the layout system via design system extensions.
|
|
86
|
+
|
|
87
|
+
:::tip
|
|
88
|
+
All the customisable styles of the layout system are contained within the styles for [`<foundation-layout>`](./docs/api/foundation-layout.foundationlayout.md). So if you want to customise the styles in addition to setting the css variables, you only need to set the styles here.
|
|
89
|
+
:::
|
|
90
|
+
|
|
91
|
+
### [Top Level Component `<foundation-layout>`](./docs/api/foundation-layout.foundationlayout.md)
|
|
92
|
+
|
|
93
|
+
Top level web component, which is used to initialise a custom layout
|
|
94
|
+
|
|
95
|
+
- **reload-buffer** : numerical attribute that controls the buffer between how long the layout is reloaded. The default
|
|
96
|
+
is 500ms. In this case, the layout is only reloaded if the child elements of the layout region are manipulated
|
|
97
|
+
once every 500ms. This is to stop the layout being reloaded over and over for every single item during initialisation.
|
|
98
|
+
The higher the value is, the more performant the component is - but the first load will appear to take longer.
|
|
99
|
+
|
|
100
|
+
::tip
|
|
101
|
+
This only applies for usage with the declarative HTML API. When the layout first loads after this amount of time,
|
|
102
|
+
it emits an [event](#event).
|
|
103
|
+
:::
|
|
104
|
+
|
|
105
|
+
### [Layout Regions](./docs/api/foundation-layout.foundationlayoutregion.md)
|
|
106
|
+
|
|
107
|
+
If you don't specify the `type` of the layout region, it defaults to `type="horizontal"`;
|
|
108
|
+
|
|
109
|
+
- **type**: `vertical`, `horizontal`, `tabs` (default `horizontal`).
|
|
110
|
+
- **size**: optional string parameter defining size, [see here](#sizing).
|
|
111
|
+
|
|
112
|
+
#### `<foundation-layout-region type="vertical">`
|
|
113
|
+
|
|
114
|
+
Indicates to the layout system that all immediate children are (by default) to be split equally within the available space of this
|
|
115
|
+
component using n-1 column split(s). Can be nested within other horizontal and vertical regions.
|
|
116
|
+
|
|
117
|
+
#### `<foundation-layout-region type="horizontal">`
|
|
118
|
+
|
|
119
|
+
Indicates to the layout system that all immediate children are (by default) to be split equally among the available space of this
|
|
120
|
+
component using n-1 row split(s). Can be nested within other horizontal and vertical regions.
|
|
121
|
+
|
|
122
|
+
#### `<foundation-layout-region type="tabs">`
|
|
123
|
+
|
|
124
|
+
Indicates to the layout system that all immediate children are to be added as tabs in the available space of this component,
|
|
125
|
+
with a tab for each child. The tabs are ordered according to which child the layout item is (e.g. the second `<foundation-layout-item>`
|
|
126
|
+
of the tab split is the second tab). The first child will be the one that is open by default. Can be nested within horizontal
|
|
127
|
+
and vertical regions, but cannot have more layout sections inside it.
|
|
128
|
+
|
|
129
|
+
### [Layout Item `<foundation-layout-item>`](./docs/api/foundation-layout.foundationlayoutitem.md)
|
|
130
|
+
|
|
131
|
+
Wrapper component that lives inside a layout section and wraps the client content. All content must be inside a layout item,
|
|
132
|
+
otherwise a runtime error will be thrown when the layout attempts to render itself on screen.
|
|
133
|
+
|
|
134
|
+
- **title**: string defining the title of the pane that contains the content. Defaults to `Item x`, where `x` is the pane number.
|
|
135
|
+
- **closable**: boolean defining whether this element is closable - Default false.
|
|
136
|
+
- **size**: optional string parameter defining size, [see here](#sizing).
|
|
137
|
+
- **registration**: optional string, which manually sets the registered name for the pane - [see here](#dynamic-registration-and-adding-items). By default, each item that doesn't have the `registration` attribute set will be a string registered sequentially starting at `"1"`.
|
|
138
|
+
|
|
139
|
+
### Sizing
|
|
140
|
+
|
|
141
|
+
The layout sections and layout item all have an _optional_ attribute:
|
|
142
|
+
|
|
143
|
+
- **size**: string defining the size. For rows, it specifies height. For columns, it specifies width. Has format `<number><size-unit>`.
|
|
144
|
+
Currently only supports units `fr` and `%`. Space is first proportionally allocated to items with sizeUnit `%`. If there is any space
|
|
145
|
+
left over (less than 100% allocated), then the remainder is allocated to the items with unit `fr` according to the fractional size.
|
|
146
|
+
If more than 100% is allocated, then an extra 50% is allocated to items with unit `fr` and is allocated to each item according to its
|
|
147
|
+
fractional size. All item sizes are then adjusted to bring the total back to 100%.
|
|
148
|
+
|
|
149
|
+
:::info
|
|
150
|
+
The size defines the size of the component _compared_ to the siblings _within_ the context of the component's parent.
|
|
151
|
+
:::
|
|
152
|
+
|
|
153
|
+
## JavaScript API
|
|
154
|
+
|
|
155
|
+
The JavaScript API is [accessed through the methods on the root layout object](./docs/api/foundation-layout.foundationlayout.md) and allows for saving/loading the layout state, and dynamically adding items to the layout at runtime.
|
|
156
|
+
|
|
157
|
+
### Dynamic registration and adding items
|
|
158
|
+
|
|
159
|
+
To have a pane displayed on the layout system, it must be *registered* with the layout system. When using the [declarative API](#declarative-html-api), the layout system takes care of this for you, but as you start to add items dynamically and then serialise the layout, you need to consider which panes are registered. See [this contained example](#contained-example), which allows the user to add pre-determined items to the layout dynamically.
|
|
160
|
+
|
|
161
|
+
:::tip
|
|
162
|
+
If you are only using the declarative API, and not using any dynamic integrations with JavaScript, then you shouldn't need to set the registration names of any items, as all the same items will be registered when you load a previously saved layout. If you are dynamically adding items as well, it is highly recommended to set the registration names of items manually. This makes it easier to figure out what is and is not registered.
|
|
163
|
+
* When using the declarative API, use the `registration` attribute on the `<foundation-layout-item>` component.
|
|
164
|
+
* When using the JavaScript API, set the `registration` optional parameter on the [registered element config](./docs/api/foundation-layout.registeredelementconfig.md).
|
|
165
|
+
:::
|
|
166
|
+
|
|
167
|
+
#### [Register Item](./docs/api/foundation-layout.foundationlayout.registeritem.md)
|
|
168
|
+
|
|
169
|
+
This API enables you to register an item at runtime, but it will not be displayed in the layout. This could be used to register components in anticipation of displaying them when loading a serialised layout - [see this example](#loading-serialised-layouts).
|
|
170
|
+
|
|
171
|
+
#### [Add Item](./docs/api/foundation-layout.foundationlayout.additem.md)
|
|
172
|
+
|
|
173
|
+
Add an item that has previously been registered with the layout.
|
|
174
|
+
|
|
175
|
+
#### [Layout Required Registrations](./docs/api/foundation-layout.foundationlayout.layoutrequiredregistrations.md)
|
|
176
|
+
|
|
177
|
+
Static function to read a layout config. It returns a list of all the required registrations required to load it in the layout system. [See this example](#loading-serialised-layouts).
|
|
178
|
+
|
|
179
|
+
#### [Get Current Registrations](./docs/api/foundation-layout.foundationlayout.registereditems.md)
|
|
180
|
+
|
|
181
|
+
Returns a list of all the items currently registered with the layout system.
|
|
182
|
+
|
|
183
|
+
:::tip
|
|
184
|
+
Use this function over `.layoutRequiredRegistrations(layout: SerialisedLayout)` to get the *current* registrations, because that will miss any items that are currently registered with the layout system, but which are not shown on the layout.
|
|
185
|
+
:::
|
|
186
|
+
|
|
187
|
+
### Serialising layout
|
|
188
|
+
|
|
189
|
+
The JavaScript API can be used to save and load layout states. This only describes the state of the dynamic layout itself. It is the responsibility of any components contained within their layout to serialise their own state, if required.
|
|
190
|
+
|
|
191
|
+
#### [Get Layout](./docs/api/foundation-layout.foundationlayout.getlayout.md)
|
|
192
|
+
|
|
193
|
+
Get an object describing the current layout so that it can be restored at a later date. This does not save any data internally to the layout. It is up to the client to store this state where appropriate for later recall (browser local storage, persistence layer, etc.)
|
|
194
|
+
|
|
195
|
+
#### [Load Layout](./docs/api/foundation-layout.foundationlayout.loadlayout.md)
|
|
196
|
+
|
|
197
|
+
Loads a serialised layout. All items that are described in the config to load must already be registered with the layout system - using either the declarative or JavaScript API. If there are items missing (could be due either to missing items or to a mismatch of registered names) then a `LayoutUsageError` will be thrown containing the names of the missing items.
|
|
198
|
+
|
|
199
|
+
## Events
|
|
200
|
+
|
|
201
|
+
### [Emitted Events](./docs/api/foundation-layout.layoutemitevents.md)
|
|
202
|
+
|
|
203
|
+
Certain actions that are performed by the user interacting with the layout emit events. See the API document linked for the events and when they're emitted. Interacting with these events allows your client code to dynamically interact with the layout, such as enabling/disabling buttons to add items to the layout when they're removed/added.
|
|
204
|
+
|
|
205
|
+
### [Received Events](./docs/api/foundation-layout.layoutreceiveevents.md)
|
|
206
|
+
|
|
207
|
+
Certain events are listened to by the container for each component, enabling the component to interact with the layout. For example, a component could emit an event to change the title of the containing window.
|
|
208
|
+
```typescript
|
|
209
|
+
this.$emit(eventType, eventDetail)
|
|
210
|
+
```
|
|
211
|
+
Each event requires a certain detail to process the event - see [the map of events to their required details](./docs/api/foundation-layout.layoutreceiveeventsdetail.md).
|
|
212
|
+
|
|
213
|
+
## Contained elements
|
|
214
|
+
|
|
215
|
+
This section concerns the behaviour of elements inside the layout. If you are using simple elements or Genesis-supplied elements this section is less of a concern, but if you are building complex custom components yourself, you will need this information.
|
|
216
|
+
|
|
217
|
+
### Element lifecycle
|
|
218
|
+
|
|
219
|
+
When an item is dragged around the layout, its lifecycle functions `connectedCallback` and `disconnectedCallback` are called.
|
|
220
|
+
It is important that the element accounts for this, such as caching data, or resizing correctly.
|
|
221
|
+
|
|
222
|
+
In the `@genesislcap/foundation-utils` package, there is a mix-in class `LifecycleMixin` which exposes two protected members `shouldRunConnect` and `shouldRunDisconnect`, which can be used to gate certain functionality. For example, if there are parts of `disconnectedCallback` that you don't want to run if the item is being dragged around the layout, you can gate it behind a `(!this.shouldRunDisconnect) return;` early return.
|
|
223
|
+
|
|
224
|
+
:::warning
|
|
225
|
+
At the very least, you must run `super` calls to the lifecycle methods, or else your custom element will not work correctly.
|
|
226
|
+
:::
|
|
227
|
+
|
|
228
|
+
### Element cloning
|
|
229
|
+
|
|
230
|
+
To enable you to add multiple items from the same `registration`, the layout system clones elements to add to the layout.
|
|
231
|
+
This is the case both when items are added with `.addItem()`, and when they are added using the declarative API. Under the hood, this uses the Node [cloneNode](https://developer.mozilla.org/en-US/docs/Web/API/Node/cloneNode) api.
|
|
232
|
+
There are certain limitations to this function, especially when using custom elements with the shadow DOM. [See troubleshooting example](#binding-events-inline-in-the-declarative-api).
|
|
233
|
+
|
|
234
|
+
In the `@genesislcap/foundation-utils` package, there is a mix-in class `LifecycleMixin` which overrides the `cloneNode` API.
|
|
235
|
+
|
|
236
|
+
```typescript
|
|
237
|
+
// Make a call to `deepClone` and manually clone children
|
|
238
|
+
override cloneNode(deep?: boolean): Node {
|
|
239
|
+
const thisClone = this.deepClone();
|
|
240
|
+
if (deep) {
|
|
241
|
+
Array.from(this.childNodes).forEach((child) => {
|
|
242
|
+
thisClone.appendChild(child.cloneNode(true));
|
|
243
|
+
});
|
|
244
|
+
}
|
|
245
|
+
return thisClone;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
// Create a new element of the same name and copy over attributes
|
|
249
|
+
deepClone(): Node {
|
|
250
|
+
const copy = document.createElement(this.tagName.toLowerCase());
|
|
251
|
+
this.getAttributeNames().forEach((at) => copy.setAttribute(at, this.getAttribute(at)));
|
|
252
|
+
return copy;
|
|
253
|
+
}
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
You can then extend the cloning functionality for your specific requirements. For example, our charts component needs to copy over `config` and `data` parameters.
|
|
257
|
+
```typescript
|
|
258
|
+
export class G2PlotChart extends LifecycleMixin(FoundationElement) {
|
|
259
|
+
...
|
|
260
|
+
override deepClone(): Node {
|
|
261
|
+
const copy = super.deepClone() as G2PlotChart;
|
|
262
|
+
copy.config = structuredClone(this.config);
|
|
263
|
+
copy.data = structuredClone(this.data);
|
|
264
|
+
return copy;
|
|
265
|
+
}
|
|
266
|
+
...
|
|
267
|
+
}
|
|
268
|
+
```
|
|
269
|
+
Some items you'll probably want to copy over are `eventListeners` and other non-attribute configuration elements on your custom element.
|
|
270
|
+
|
|
271
|
+
## Examples
|
|
272
|
+
|
|
273
|
+
### Simple example
|
|
274
|
+
|
|
275
|
+
Simple example with a vertical split and two items that will take up equal space.
|
|
276
|
+
|
|
277
|
+
```html
|
|
278
|
+
<foundation-layout>
|
|
279
|
+
<foundation-layout-region type="horizontal">
|
|
280
|
+
<foundation-layout-item title="Component 1">
|
|
281
|
+
<!-- Content -->
|
|
282
|
+
</foundation-layout-item>
|
|
283
|
+
<foundation-layout-item title="Component 2">
|
|
284
|
+
<!-- Content -->
|
|
285
|
+
</foundation-layout-item>
|
|
286
|
+
</foundation-layout-region>
|
|
287
|
+
</foundation-layout>
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
Will be rendered as:
|
|
291
|
+
|
|
292
|
+
```
|
|
293
|
+
+-----------------------------------------------------+
|
|
294
|
+
| |
|
|
295
|
+
| Component 1 Contents |
|
|
296
|
+
| |
|
|
297
|
+
+-----------------------------------------------------+
|
|
298
|
+
| |
|
|
299
|
+
| Component 2 Contents |
|
|
300
|
+
| |
|
|
301
|
+
+-----------------------------------------------------+
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
### Nested example
|
|
305
|
+
|
|
306
|
+
A slightly more complicated example:
|
|
307
|
+
|
|
308
|
+
```html
|
|
309
|
+
<foundation-layout>
|
|
310
|
+
<foundation-layout-region type="vertical">
|
|
311
|
+
<foundation-layout-item title="Component 1" size="25%" closable>
|
|
312
|
+
<!-- Content -->
|
|
313
|
+
</foundation-layout-item>
|
|
314
|
+
|
|
315
|
+
<foundation-layout-region type="horizontal">
|
|
316
|
+
<foundation-layout-item title="Component 2">
|
|
317
|
+
<!-- Content -->
|
|
318
|
+
</foundation-layout-item>
|
|
319
|
+
<foundation-layout-item title="Component 3">
|
|
320
|
+
<!-- Content -->
|
|
321
|
+
</foundation-layout-item>
|
|
322
|
+
</foundation-layout-region>
|
|
323
|
+
</foundation-layout-region>
|
|
324
|
+
|
|
325
|
+
</foundation-layout>
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
Would render the following:
|
|
329
|
+
|
|
330
|
+
```
|
|
331
|
+
+-------------+---------------------------------------+
|
|
332
|
+
| | |
|
|
333
|
+
| | Component 2 Contents |
|
|
334
|
+
| Component | |
|
|
335
|
+
| 1 +---------------------------------------+
|
|
336
|
+
| Contents | |
|
|
337
|
+
| | Component 3 Contents |
|
|
338
|
+
| | |
|
|
339
|
+
+-------------+---------------------------------------+
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
Component 1 has a Close button. By default, Component 1 would be 50% width and 2 and 3 would take up the other 50% width, but here we set `25%`
|
|
343
|
+
as the width of Component 1 layout item (width because it is the size in the context of a vertical split).
|
|
344
|
+
|
|
345
|
+
### Multi-nested example
|
|
346
|
+
|
|
347
|
+
If instead we had:
|
|
348
|
+
|
|
349
|
+
```html
|
|
350
|
+
<foundation-layout>
|
|
351
|
+
<foundation-layout-region type="vertical">
|
|
352
|
+
<foundation-layout-item title="Component 1" size="25%" closable>
|
|
353
|
+
<!-- Content -->
|
|
354
|
+
</foundation-layout-item>
|
|
355
|
+
|
|
356
|
+
<foundation-layout-region type="horizontal">
|
|
357
|
+
<foundation-layout-region type="vertical">
|
|
358
|
+
<foundation-layout-item title="Component 2">
|
|
359
|
+
<!-- Content -->
|
|
360
|
+
</foundation-layout-item>
|
|
361
|
+
<foundation-layout-item title="Component 3">
|
|
362
|
+
<!-- Content -->
|
|
363
|
+
</foundation-layout-item>
|
|
364
|
+
<foundation-layout-item title="Component 4">
|
|
365
|
+
<!-- Content -->
|
|
366
|
+
</foundation-layout-item>
|
|
367
|
+
</foundation-layout-region>
|
|
368
|
+
|
|
369
|
+
<foundation-layout-region type="tabs">
|
|
370
|
+
<foundation-layout-item title="Component 5">
|
|
371
|
+
<!-- Content -->
|
|
372
|
+
</foundation-layout-item>
|
|
373
|
+
<foundation-layout-item title="Component 6">
|
|
374
|
+
<!-- Content -->
|
|
375
|
+
</foundation-layout-item>
|
|
376
|
+
</foundation-layout-region>
|
|
377
|
+
</foundation-layout-region>
|
|
378
|
+
</foundation-layout-region>
|
|
379
|
+
|
|
380
|
+
</foundation-layout>
|
|
381
|
+
```
|
|
382
|
+
|
|
383
|
+
This would render the following:
|
|
384
|
+
|
|
385
|
+
```
|
|
386
|
+
+-------------+------------+-------------+------------+
|
|
387
|
+
| | | | |
|
|
388
|
+
| | Comp 2 | Comp 3 | Comp 4 |
|
|
389
|
+
| Component | | | |
|
|
390
|
+
| 1 +------------+-------------+------------+
|
|
391
|
+
| Contents |_5_|_6_| |
|
|
392
|
+
| | Component 5 Contents |
|
|
393
|
+
| | |
|
|
394
|
+
+-------------+---------------------------------------+
|
|
395
|
+
```
|
|
396
|
+
Component 1 has a Close button. Component 1 takes up 25% of the initial width. Components 2,3,4 take up a third of the _remaining_ width between them
|
|
397
|
+
(default behaviour) and 5 and 6 are tabbed.
|
|
398
|
+
|
|
399
|
+
### `repeat` directive
|
|
400
|
+
|
|
401
|
+
You can use [FAST template directives](https://www.fast.design/docs/fast-element/using-directives) such as `repeat`
|
|
402
|
+
|
|
403
|
+
```javascript
|
|
404
|
+
interface Position {
|
|
405
|
+
symbol: string;
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
class Commodities extends FASTElement {
|
|
409
|
+
positions: Position[] // Not @observable - see following section
|
|
410
|
+
|
|
411
|
+
...
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
const template = html<Commodities>`
|
|
415
|
+
<foundation-layout>
|
|
416
|
+
<foundation-layout-region type="horizontal">
|
|
417
|
+
${when(x => x.positions, html<Position>`
|
|
418
|
+
<foundation-layout-item title="${x => x.symbol}">
|
|
419
|
+
<chart symbol="${x => x.symbol}"></chart>
|
|
420
|
+
</foundation-layout-item>`)}
|
|
421
|
+
</foundation-layout-region>
|
|
422
|
+
</foundation-layout>`;
|
|
423
|
+
```
|
|
424
|
+
|
|
425
|
+
For an example where the `Commodities` object has three positions, you will see the following output:
|
|
426
|
+
```
|
|
427
|
+
+-----------------------------------------------------+
|
|
428
|
+
| Component 1 Contents |
|
|
429
|
+
+-----------------------------------------------------+
|
|
430
|
+
| Component 2 Contents |
|
|
431
|
+
+-----------------------------------------------------+
|
|
432
|
+
| Component 3 Contents |
|
|
433
|
+
+-----------------------------------------------------+
|
|
434
|
+
```
|
|
435
|
+
|
|
436
|
+
|
|
437
|
+
:::note
|
|
438
|
+
`<chart>` is just an example component; it doesn't exist within `foundation-ui`.
|
|
439
|
+
:::
|
|
440
|
+
|
|
441
|
+
### `when` directive
|
|
442
|
+
|
|
443
|
+
Using the `when` directive:
|
|
444
|
+
|
|
445
|
+
```javascript
|
|
446
|
+
@customElement({
|
|
447
|
+
name: 'my-element',
|
|
448
|
+
template,
|
|
449
|
+
})
|
|
450
|
+
class Analytics extends FASTElement {
|
|
451
|
+
showIndexFunds = true; // not @observable
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
var template = html<Analytics>`
|
|
455
|
+
<button class="toggle">Toggle Index</button>
|
|
456
|
+
<foundation-layout>
|
|
457
|
+
<foundation-layout-region>
|
|
458
|
+
<foundation-layout-item>
|
|
459
|
+
<chart type="stocks"></chart>
|
|
460
|
+
</foundation-layout-item>
|
|
461
|
+
|
|
462
|
+
${when(x => x.showIndexFunds, html`
|
|
463
|
+
<foundation-layout-item>
|
|
464
|
+
<chart type="index-funds"></chart>
|
|
465
|
+
</foundation-layout-item>
|
|
466
|
+
`)}
|
|
467
|
+
|
|
468
|
+
</foundation-layout-region>
|
|
469
|
+
</foundation-layout>
|
|
470
|
+
`;
|
|
471
|
+
```
|
|
472
|
+
|
|
473
|
+
You would see both items rendered like this:
|
|
474
|
+
```
|
|
475
|
+
+---------------------------------------------+
|
|
476
|
+
| Stocks Chart |
|
|
477
|
+
+---------------------------------------------+
|
|
478
|
+
| Index Chart |
|
|
479
|
+
+---------------------------------------------+
|
|
480
|
+
```
|
|
481
|
+
|
|
482
|
+
If you had `showIndexFunds = false;` then only the `Stocks Chart` would be rendered.
|
|
483
|
+
|
|
484
|
+
:::danger
|
|
485
|
+
Directives are for initialising the layout only and should *not* be used with changing `@observable` attributes which would cause the
|
|
486
|
+
layout to reinitialise incorrectly - this will duplicate the panels. For example, you can use the
|
|
487
|
+
`when` directive to conditionally render a pane during initialisation, but not to toggle whether to show/hide the pane afterwards.
|
|
488
|
+
See [this example](#observables-with-directives).
|
|
489
|
+
:::
|
|
490
|
+
|
|
491
|
+
### Multiple instances
|
|
492
|
+
|
|
493
|
+
Consider the following example:
|
|
494
|
+
```html
|
|
495
|
+
<div class="container" style="display: grid; grid-template-columns: 1fr; grid-auto-rows: minmax(46vh, auto)">
|
|
496
|
+
<div style="display: block; position: relative;">
|
|
497
|
+
<foundation-layout>
|
|
498
|
+
<foundation-layout-region>
|
|
499
|
+
<foundation-layout-item><h1>Item 1</h1></foundation-layout-item>
|
|
500
|
+
<foundation-layout-item><h1>Item 2</h1></foundation-layout-item>
|
|
501
|
+
</foundation-layout-region>
|
|
502
|
+
</foundation-layout>
|
|
503
|
+
</div>
|
|
504
|
+
<div style="display: block; position: relative;">
|
|
505
|
+
<foundation-layout>
|
|
506
|
+
<foundation-layout-region type="vertical">
|
|
507
|
+
<foundation-layout-item><h1>Item 3</h1></foundation-layout-item>
|
|
508
|
+
<foundation-layout-item><h1>Item 4</h1></foundation-layout-item>
|
|
509
|
+
</foundation-layout-region>
|
|
510
|
+
</foundation-layout>
|
|
511
|
+
</div>
|
|
512
|
+
</div>
|
|
513
|
+
```
|
|
514
|
+
|
|
515
|
+
This describes the following layout:
|
|
516
|
+
```
|
|
517
|
+
+---------------------------------------------+
|
|
518
|
+
| Item 1 |
|
|
519
|
+
+---------------------------------------------+
|
|
520
|
+
| Item 2 |
|
|
521
|
+
+---------------------------------------------+
|
|
522
|
+
|
|
523
|
+
+----------------------+----------------------+
|
|
524
|
+
| | |
|
|
525
|
+
| Item 3 | Item 4 |
|
|
526
|
+
| | |
|
|
527
|
+
+----------------------+----------------------+
|
|
528
|
+
```
|
|
529
|
+
Here a grid region has been used to style two completely separate instances of the dynamic layout. Even though we have named each
|
|
530
|
+
`<h1>` sequentially, the two layouts are completely separate and the default titles of each tab (Item 1 and Item 2 for both layouts),
|
|
531
|
+
will reflect this. You can configure each layout separately, and you cannot drag layout items from one layout into the other one.
|
|
532
|
+
|
|
533
|
+
:::info
|
|
534
|
+
This is just an example; you could have more than two layouts on a page or style them with a different method to the grid.
|
|
535
|
+
:::
|
|
536
|
+
|
|
537
|
+
### Adding items dynamically
|
|
538
|
+
|
|
539
|
+
This is an example of using the JavaScript API to add items onto the layout at runtime. Before reading this example you should familiarise yourself with the [API Section](#javascript-api).
|
|
540
|
+
|
|
541
|
+
Say you want the user to be able to choose between three different types of item tht can be put onto the layout - a profile-management table, and a pie & column chart.
|
|
542
|
+
|
|
543
|
+
```typescript
|
|
544
|
+
// Can either create an element and initialise it completely using JavaScript
|
|
545
|
+
const profileManagement = document.createElement('profile-management');
|
|
546
|
+
// Or could grab a reference to one you create via FAST markup
|
|
547
|
+
const pieChart = document.getElementById('pie-chart');
|
|
548
|
+
// In idiomatic FAST we can have a reference using `ref` directive
|
|
549
|
+
// const colChart = this.columnChart;
|
|
550
|
+
```
|
|
551
|
+
|
|
552
|
+
We can then register these elements with the layout system. Registering it with the layout system removes it from its original location.
|
|
553
|
+
```typescript
|
|
554
|
+
// Using a duplicate registration name is a runtime error
|
|
555
|
+
this.layout.registerItem('profile', [profileManagement]);
|
|
556
|
+
this.layout.registerItem('pie', [pieChart]);
|
|
557
|
+
this.layout.registerItem('colChart', [this.columnChart]);
|
|
558
|
+
```
|
|
559
|
+
|
|
560
|
+
Finally, use the `addItem` API to add a pane onto the layout using a previously registered item.
|
|
561
|
+
```typescript
|
|
562
|
+
this.layout.addItem({
|
|
563
|
+
registration: 'profile',
|
|
564
|
+
name: 'Profile Management',
|
|
565
|
+
closable: true,
|
|
566
|
+
})
|
|
567
|
+
```
|
|
568
|
+
Using `addItem` with a `registration` that has not been set is a runtime error. Remember `addItem` has an optional second parameter for setting the placement of the new pane.
|
|
569
|
+
|
|
570
|
+
:::tip
|
|
571
|
+
Items registered using the declarative API use the same pool of registration names, so you can also use `addItem` to add them to the layout too.
|
|
572
|
+
:::
|
|
573
|
+
|
|
574
|
+
#### Contained example
|
|
575
|
+
|
|
576
|
+
This is a complete example of the above, omitting imports.
|
|
577
|
+
|
|
578
|
+
```typescript
|
|
579
|
+
// template
|
|
580
|
+
export const template = html<ContainedExample>`
|
|
581
|
+
<div style="display: grid; grid-template-columns: 1fr; grid-auto-rows: minmax(7vh, auto)">
|
|
582
|
+
<div style="display: block; position: relative;">
|
|
583
|
+
<foundation-button @click=${(x) => x.addItem('1')}>Test 1</foundation-button>
|
|
584
|
+
<foundation-button @click=${(x) => x.addItem('2')}>Test 2</foundation-button>
|
|
585
|
+
<foundation-button @click=${(x) => x.addItem('3')}>Test 3</foundation-button>
|
|
586
|
+
</div>
|
|
587
|
+
<div style="display: block; position: relative; grid-row-start: 2; grid-row-end: 12;">
|
|
588
|
+
<foundation-layout ${ref('containedExampleLayout')}></foundation-layout>
|
|
589
|
+
</div>
|
|
590
|
+
</div>
|
|
591
|
+
`;
|
|
592
|
+
|
|
593
|
+
// class
|
|
594
|
+
@customElement({
|
|
595
|
+
name: 'contained-example',
|
|
596
|
+
template,
|
|
597
|
+
})
|
|
598
|
+
export class ContainedExample extends FASTElement {
|
|
599
|
+
containedExampleLayout: FoundationLayout;
|
|
600
|
+
private _addedPaneCount = 0;
|
|
601
|
+
|
|
602
|
+
connectedCallback(): void {
|
|
603
|
+
super.connectedCallback();
|
|
604
|
+
|
|
605
|
+
const h1 = document.createElement('h1');
|
|
606
|
+
h1.innerHTML = 'Example 1';
|
|
607
|
+
const p1 = document.createElement('p');
|
|
608
|
+
p1.innerHTML = 'Ex 1';
|
|
609
|
+
|
|
610
|
+
const h2 = document.createElement('h2');
|
|
611
|
+
h2.innerHTML = 'Example 2';
|
|
612
|
+
const p2 = document.createElement('p');
|
|
613
|
+
p2.innerHTML = 'Ex 2';
|
|
614
|
+
|
|
615
|
+
const h3 = document.createElement('h3');
|
|
616
|
+
h3.innerHTML = 'Example 3';
|
|
617
|
+
const p3 = document.createElement('p');
|
|
618
|
+
p3.innerHTML = 'Ex 3';
|
|
619
|
+
|
|
620
|
+
this.containedExampleLayout.registerItem('1', [h1, p1]);
|
|
621
|
+
this.containedExampleLayout.registerItem('2', [h2, p2]);
|
|
622
|
+
this.containedExampleLayout.registerItem('3', [h3, p3]);
|
|
623
|
+
}
|
|
624
|
+
|
|
625
|
+
addItem(registration: string) {
|
|
626
|
+
this.containedExampleLayout.addItem({
|
|
627
|
+
registration,
|
|
628
|
+
title: `${registration} (${(this._addedPaneCount += 1)})`,
|
|
629
|
+
closable: true,
|
|
630
|
+
});
|
|
631
|
+
}
|
|
632
|
+
}
|
|
633
|
+
```
|
|
634
|
+
|
|
635
|
+
### Loading serialised layouts
|
|
636
|
+
|
|
637
|
+
This is an elaborate example of using the JavaScript API with consideration of the registered names. Before reading this example, you should familiarise yourself with the [API Section](#javascript-api):
|
|
638
|
+
|
|
639
|
+
```html
|
|
640
|
+
<foundation-layout>
|
|
641
|
+
<foundation-layout-region type="horizontal">
|
|
642
|
+
<foundation-layout-item title="Trades" registration="trades">
|
|
643
|
+
<!-- Content -->
|
|
644
|
+
</foundation-layout-item>
|
|
645
|
+
<foundation-layout-item title="Users" registration="users">
|
|
646
|
+
<!-- Content -->
|
|
647
|
+
</foundation-layout-item>
|
|
648
|
+
</foundation-layout-region>
|
|
649
|
+
</foundation-layout>
|
|
650
|
+
```
|
|
651
|
+
|
|
652
|
+
We can use `layoutRequiredRegistrations()` on the config returned from `getLayout()` to see the registered names that are required to load the layout.
|
|
653
|
+
|
|
654
|
+
```javascript
|
|
655
|
+
const layout = document.querySelector('foundation-layout'); // as FoundatonLayout in TypeScript;
|
|
656
|
+
const layoutConfig = layout.getLayout();
|
|
657
|
+
console.log(FoundatonLayout.layoutRequiredRegistrations(layoutConfig))
|
|
658
|
+
```
|
|
659
|
+
This will log `['trades','users']` because these are the two registered panes. You can then load any layout that only contains either/both of these items.
|
|
660
|
+
|
|
661
|
+
Consider the situation where we dynamically add an item to the right-hand side of the layout.
|
|
662
|
+
```javascript
|
|
663
|
+
const newItem = document.createElement('p'); //simple example
|
|
664
|
+
newItem.innerText = 'Test';
|
|
665
|
+
|
|
666
|
+
layout.registerItem(test, [newItem]);
|
|
667
|
+
const layoutConfigTwo = layout.getLayout()
|
|
668
|
+
console.log(FoundationLayout.layoutRequiredRegistrations(layoutConfigTwo));
|
|
669
|
+
```
|
|
670
|
+
Now we get `[ "test", "trades", "users"]` as the output, because to load `layoutConfigTwo` we now need all three of those registered panes.
|
|
671
|
+
|
|
672
|
+
Consider now where the user refreshes the page to go back to the original state of the layout with just the two elements added, but then tries to load:
|
|
673
|
+
|
|
674
|
+
`layoutConfigTwo`:
|
|
675
|
+
```javascript
|
|
676
|
+
// User has refreshed page
|
|
677
|
+
|
|
678
|
+
console.log(layout.registeredItems());
|
|
679
|
+
// Ouputs ['trades','users']
|
|
680
|
+
|
|
681
|
+
layout.loadLayout(layoutConfigTwo);
|
|
682
|
+
// Uncaught Error: Trying to load layout with extra components. The component(s) not currently loaded are "test"
|
|
683
|
+
```
|
|
684
|
+
Notice the error message says that the `test` component is missing. This is because it was required as part of the layout when we used `getLayout()`, but it hasn't been added as part of the layout now. If we added the item using `registerItem()` we could subsequently run `layout.loadLayout(layoutConfigTwo);` to load the layout successfully.
|
|
685
|
+
|
|
686
|
+
:::warning
|
|
687
|
+
Just because an item is not displayed on the layout does not mean it is not registered. `.getLayout()` gets only the current layout config, so you cannot use it to see every single item that is currently registered (unless every item is added). This is why you should use `.registeredItems()` to get the currently registered items.
|
|
688
|
+
:::
|
|
689
|
+
|
|
690
|
+
#### Proactively registering items
|
|
691
|
+
|
|
692
|
+
Here is a simple approach to ensure that all items are registered when you load a layout; loop through all the items that you could possibly load and register them.
|
|
693
|
+
|
|
694
|
+
```javascript
|
|
695
|
+
const allItems = [
|
|
696
|
+
{registration: 'trades', elements: [...], },
|
|
697
|
+
{registration: 'users', elements: [...], },
|
|
698
|
+
{registration: 'profiles', elements: [...], },
|
|
699
|
+
{registration: 'notifications', elements: [...], },
|
|
700
|
+
];
|
|
701
|
+
|
|
702
|
+
allItems.forEach(({registration, elements}) => {
|
|
703
|
+
layout.registerItem(registration, elements);
|
|
704
|
+
})
|
|
705
|
+
```
|
|
706
|
+
Now all those items will be registered with the layout for potential use when calling `loadLayout()`, or added using `addItem()`.
|
|
707
|
+
|
|
708
|
+
#### Reactively registering items
|
|
709
|
+
|
|
710
|
+
Alternatively, you could query the current layout and the layout you want to load to see if there are any missing registered items; you can then register the missing ones. Using our previous examples:
|
|
711
|
+
|
|
712
|
+
```javascript
|
|
713
|
+
const currentRegistrations = FoundatonLayout.registeredItems();
|
|
714
|
+
// ['trades','users']
|
|
715
|
+
const requiredRegistrations = FoundatonLayout.layoutRequiredRegistrations(layoutConfigTwo);
|
|
716
|
+
// ['test','trades','users']
|
|
717
|
+
|
|
718
|
+
// We can see 'test' is missing and therefore we should register it
|
|
719
|
+
layout.registerItem(test, [element]);
|
|
720
|
+
```
|
|
721
|
+
|
|
722
|
+
:::info
|
|
723
|
+
Only items _missing_ from the `requiredRegistrations` is an issue. If there are items in the `currentRegistrations` that are not in `requiredRegistrations`, this is *not* an issue - because these will simply be unused registrations.
|
|
724
|
+
:::
|
|
725
|
+
|
|
726
|
+
## Incorrect examples
|
|
727
|
+
|
|
728
|
+
The following section contains examples of incorrect usage, which are useful for troubleshooting.
|
|
729
|
+
|
|
730
|
+
### Non-layout child
|
|
731
|
+
|
|
732
|
+
The following example is invalid:
|
|
733
|
+
|
|
734
|
+
```html
|
|
735
|
+
<foundation-layout>
|
|
736
|
+
<foundation-layout-region type="horizontal">
|
|
737
|
+
<h1>My splits</h1>
|
|
738
|
+
<foundation-layout-item title="Component 1">
|
|
739
|
+
<!-- Content -->
|
|
740
|
+
</foundation-layout-item>
|
|
741
|
+
<foundation-layout-item title="Component 2">
|
|
742
|
+
<!-- Content -->
|
|
743
|
+
</foundation-layout-item>
|
|
744
|
+
</foundation-layout-region>
|
|
745
|
+
</foundation-layout>
|
|
746
|
+
```
|
|
747
|
+
This is because there is a child of one of the layout regions which isn't another layout region or layout item (the `<h1>`). This will throw a runtime error.
|
|
748
|
+
|
|
749
|
+
### Layout region in tabs
|
|
750
|
+
|
|
751
|
+
The following example is invalid:
|
|
752
|
+
|
|
753
|
+
```html
|
|
754
|
+
<foundation-layout>
|
|
755
|
+
<foundation-layout-region type="tabs">
|
|
756
|
+
|
|
757
|
+
<foundation-layout-region type="vertical">
|
|
758
|
+
<foundation-layout-item title="Component 1">
|
|
759
|
+
<!-- Content -->
|
|
760
|
+
</foundation-layout-item>
|
|
761
|
+
<foundation-layout-item title="Component 2">
|
|
762
|
+
<!-- Content -->
|
|
763
|
+
</foundation-layout-item>
|
|
764
|
+
</foundation-layout-region>
|
|
765
|
+
|
|
766
|
+
<foundation-layout-item title="Component 3">
|
|
767
|
+
<!-- Content -->
|
|
768
|
+
</foundation-layout-item>
|
|
769
|
+
|
|
770
|
+
</foundation-layout-region>
|
|
771
|
+
</foundation-layout>
|
|
772
|
+
```
|
|
773
|
+
This is because you cannot have more layout regions nested inside a tab region. You will get undefined behaviour.
|
|
774
|
+
|
|
775
|
+
|
|
776
|
+
### Multiple items in root
|
|
777
|
+
|
|
778
|
+
The following example is invalid:
|
|
779
|
+
|
|
780
|
+
```html
|
|
781
|
+
<foundation-layout>
|
|
782
|
+
<foundation-layout-item title="Component 1">
|
|
783
|
+
<!-- Content -->
|
|
784
|
+
</foundation-layout-item>
|
|
785
|
+
<foundation-layout-item title="Component 2">
|
|
786
|
+
<!-- Content -->
|
|
787
|
+
</foundation-layout-item>
|
|
788
|
+
<foundation-layout-item title="Component 3">
|
|
789
|
+
<!-- Content -->
|
|
790
|
+
</foundation-layout-item>
|
|
791
|
+
</foundation-layout>
|
|
792
|
+
```
|
|
793
|
+
This is because you cannot have multiple layout elements as the immediate child of the layout root. You will get a runtime error.
|
|
794
|
+
|
|
795
|
+
### Nested item
|
|
796
|
+
|
|
797
|
+
The following example is invalid:
|
|
798
|
+
|
|
799
|
+
```html
|
|
800
|
+
<foundation-layout>
|
|
801
|
+
<foundation-layout-item title="Component 1">
|
|
802
|
+
<foundation-layout-item title="Component 2">
|
|
803
|
+
<!-- Content -->
|
|
804
|
+
</foundation-layout-item>
|
|
805
|
+
<foundation-layout-item title="Component 3">
|
|
806
|
+
<!-- Content -->
|
|
807
|
+
</foundation-layout-item>
|
|
808
|
+
</foundation-layout-item>
|
|
809
|
+
</foundation-layout>
|
|
810
|
+
```
|
|
811
|
+
This is because you cannot have `<foundation-layout-item>` inside other `<foundation-layout-item>`. You will get a runtime error.
|
|
812
|
+
|
|
813
|
+
### Observables with directives
|
|
814
|
+
|
|
815
|
+
The following is invalid:
|
|
816
|
+
|
|
817
|
+
```javascript
|
|
818
|
+
@customElement({
|
|
819
|
+
name: 'my-element',
|
|
820
|
+
template,
|
|
821
|
+
})
|
|
822
|
+
class Analytics extends FASTElement {
|
|
823
|
+
@observable showIndexFunds = true;
|
|
824
|
+
|
|
825
|
+
toggleShowIndexFunds() {
|
|
826
|
+
this.showIndexFunds = !this.showIndexFunds;
|
|
827
|
+
}
|
|
828
|
+
}
|
|
829
|
+
|
|
830
|
+
var template = html<Analytics>`
|
|
831
|
+
<button
|
|
832
|
+
class="toggle"
|
|
833
|
+
@click=${x => x.toggleShowIndexFunds()}
|
|
834
|
+
>Toggle Index</button>
|
|
835
|
+
<foundation-layout>
|
|
836
|
+
<foundation-layout-region>
|
|
837
|
+
<foundation-layout-item>
|
|
838
|
+
<chart type="stocks"></chart>
|
|
839
|
+
</foundation-layout-item>
|
|
840
|
+
|
|
841
|
+
${when(x => x.showIndexFunds, html`
|
|
842
|
+
<foundation-layout-item>
|
|
843
|
+
<chart type="index-funds"></chart>
|
|
844
|
+
</foundation-layout-item>
|
|
845
|
+
`)}
|
|
846
|
+
|
|
847
|
+
</foundation-layout-region>
|
|
848
|
+
</foundation-layout>
|
|
849
|
+
`;
|
|
850
|
+
```
|
|
851
|
+
|
|
852
|
+
Initially you will see both items correctly rendered like this:
|
|
853
|
+
```
|
|
854
|
+
+---------------------------------------------+
|
|
855
|
+
| Stocks Chart |
|
|
856
|
+
+---------------------------------------------+
|
|
857
|
+
| Index Chart |
|
|
858
|
+
+---------------------------------------------+
|
|
859
|
+
```
|
|
860
|
+
But as the user clicks the toggle button, the `Index Chart` will not be taken away and added back in.
|
|
861
|
+
Instead, it will be added as a duplicate every time the observable is set true. Additionally, the contents
|
|
862
|
+
of the panel will be wiped as duplicates are added.
|
|
863
|
+
|
|
864
|
+
To work around this, you would use FAST directives inside custom web components inside the layout.
|
|
865
|
+
|
|
866
|
+
### Binding events inline in the declarative API
|
|
867
|
+
The following example is invalid:
|
|
868
|
+
|
|
869
|
+
```html
|
|
870
|
+
<foundation-layout>
|
|
871
|
+
<foundation-layout-item>
|
|
872
|
+
<input type="checkbox" @change=${(x,c) => x.doSomething()} />
|
|
873
|
+
</foundation-layout-item>
|
|
874
|
+
</foundation-layout>
|
|
875
|
+
```
|
|
876
|
+
|
|
877
|
+
Because of a limitation in the [cloneNode() API](https://developer.mozilla.org/en-US/docs/Web/API/Node/cloneNode), event listeners are *not* copied.
|
|
878
|
+
This process is part of the process of adding an item to the layout, using both the declarative HTML and JavaScript APIs. So while you will see
|
|
879
|
+
a checkbox on the screen as part of the layout, the event listener will *not* fire when you `change` the checkbox. This applies to all items and events.
|
|
880
|
+
|
|
881
|
+
The idiomatic FAST way of implementing this event binding is to create a custom element and attach the event internally.
|
|
882
|
+
|
|
883
|
+
```typescript
|
|
884
|
+
// template
|
|
885
|
+
export const exampleComponentTemplate = html<ExampleComponent>`
|
|
886
|
+
<template>
|
|
887
|
+
<input type="checkbox" ${ref('checkbox')} @change=${(x, c) => x.doSomething()} />
|
|
888
|
+
</template>
|
|
889
|
+
`;
|
|
890
|
+
|
|
891
|
+
// model
|
|
892
|
+
@customElement({
|
|
893
|
+
name: 'example-component',
|
|
894
|
+
template: exampleComponentTemplate,
|
|
895
|
+
})
|
|
896
|
+
export class ExampleComponent extends FASTElement {
|
|
897
|
+
checkbox: Checkbox;
|
|
898
|
+
doSomething() { } // do something important
|
|
899
|
+
}
|
|
900
|
+
```
|
|
901
|
+
|
|
902
|
+
You can then use the custom component in the layout:
|
|
903
|
+
|
|
904
|
+
```html
|
|
905
|
+
<foundation-layout>
|
|
906
|
+
<foundation-layout-item>
|
|
907
|
+
<example-component><example-component/>
|
|
908
|
+
</foundation-layout-item>
|
|
909
|
+
</foundation-layout>
|
|
910
|
+
```
|
|
911
|
+
|
|
912
|
+
|
|
913
|
+
|
|
914
|
+
## License
|
|
915
|
+
|
|
916
|
+
Note: this project provides front end dependencies and uses licensed components listed in the next section, thus licenses for those components are required during development. Contact [Genesis Global](https://genesis.global/contact-us/) for more details.
|