Layout
Now let's use another property named widget
. Widgets will soon be explained in more detail. But
now we will use a built-in widget called "Layout"
apps/testing-buttons.js
| import { Application, Layout } from "@codecoupler/cc-ui";
import buttons from "./custom-buttons";
import MyFirstWidget from "../widgets/my-first-widget.js";
export default class extends Application {
static ui = {
name: "Testing Buttons",
iconHtml: '<i class="fas fa-seedling fa-fw"></i>'
};
async init() {
let layout = {
root: {
type: "widget",
widget: MyFirstWidget,
options: {
text: "Hallo Everyone"
}
}
};
await super.init({
panel: {
panelSize: "820 600",
headerTitle: "My First Title",
footerToolbar:
'<i class="far fa-hand-point-right mx-1"></i> [blocks][hints][alerts][close]'
},
buttons: buttons,
widget: {
widget: Layout,
options: layout
}
});
}
}
|
You see now a new property widget
which loads a widget named Layout
into the content area of the
application panel. The options have been moved to a separate variable layout
.
In the options, starting with a root
you can split the main content area of the application into
parts. Into this parts you can load widgets. In this example we have only one area defined and load
the widget MyFirstWidget
. So before you can compile this application we need to create of course
the widget:
widgets/my-first-widget.js
| import { Widget } from "@codecoupler/cc-ui";
export default class extends Widget {
async init(env, options) {
env.$element.html(`
<h1>My First Widget!</h1>
<p>Text: ${options.text}</p>
`);
}
}
|
For now it is only important to know, that you have an init
method where you receive with
env.element
(HTMLElement) or env.$element
(jQuery Object) the target element what you can fill
with live. In options
you receive the object you have defined in your application with the
property options
.
Starting the application you will see your first widget running. Not very spectacular, so lets
define a second area:
apps/testing-buttons.js
| import { Application, Layout } from "@codecoupler/cc-ui";
import buttons from "./custom-buttons";
import MyFirstWidget from "../widgets/my-first-widget.js";
export default class extends Application {
static ui = {
name: "Testing Buttons",
iconHtml: '<i class="fas fa-seedling fa-fw"></i>'
};
async init() {
let layout = {
root: {
type: "row",
content: [
{
type: "widget",
widget: MyFirstWidget,
options: {
text: "Hallo Everyone"
}
},
{
type: "widget",
widget: MyFirstWidget,
options: {
text: "How are you?"
}
}
]
}
};
await super.init({
panel: {
panelSize: "820 600",
headerTitle: "My First Title",
footerToolbar:
'<i class="far fa-hand-point-right mx-1"></i> [blocks][hints][alerts][close]'
},
buttons: buttons,
widget: {
widget: Layout,
options: layout
}
});
}
}
|
We have used the same widget for a second area just with another parameter value defined in text
.
Starting you application you see two areas which can be resized.
Now let's go one step further to illustrate how you can use the types row
, column
and
component
and how they can be nested:
apps/testing-buttons.js
| import { Application, Layout } from "@codecoupler/cc-ui";
import buttons from "./custom-buttons";
import MyFirstWidget from "../widgets/my-first-widget.js";
export default class extends Application {
static ui = {
name: "Testing Buttons",
iconHtml: '<i class="fas fa-seedling fa-fw"></i>'
};
async init() {
let layout = {
root: {
type: "row",
content: [
{
type: "widget",
widget: MyFirstWidget,
options: {
text: "Hallo Everyone"
}
},
{
type: "column",
content: [
{
type: "widget",
widget: MyFirstWidget,
options: {
text: "How are you?"
}
},
{
type: "widget",
widget: MyFirstWidget,
options: {
text: "I'm fine, thanks!"
}
}
]
}
]
}
};
await super.init({
panel: {
panelSize: "820 600",
headerTitle: "My First Title",
footerToolbar:
'<i class="far fa-hand-point-right mx-1"></i> [blocks][hints][alerts][close]'
},
buttons: buttons,
widget: {
widget: Layout,
options: layout
}
});
}
}
|
Resizing the areas is nice, but what about draging them around and rearange them? No problem. You
have to insert a new property header
into the layout
object where you can configure the layout.
We use now show
and set this to true
. Please mention that we have set an attribute title
for
each widget. You will understand why, soon:
apps/testing-buttons.js
| import { Application, Layout } from "@codecoupler/cc-ui";
import buttons from "./custom-buttons";
import MyFirstWidget from "../widgets/my-first-widget.js";
export default class extends Application {
static ui = {
name: "Testing Buttons",
iconHtml: '<i class="fas fa-seedling fa-fw"></i>'
};
async init() {
let layout = {
header: {
show: true
},
root: {
type: "row",
content: [
{
type: "widget",
title: "Number 1",
widget: MyFirstWidget,
options: {
text: "Hallo Everyone"
}
},
{
type: "column",
content: [
{
type: "widget",
title: "Number 2",
widget: MyFirstWidget,
options: {
text: "How are you?"
}
},
{
type: "widget",
title: "Number 3",
widget: MyFirstWidget,
options: {
text: "I'm fine, thanks!"
}
}
]
}
]
}
};
await super.init({
panel: {
panelSize: "820 600",
headerTitle: "My First Title",
footerToolbar:
'<i class="far fa-hand-point-right mx-1"></i> [blocks][hints][alerts][close]'
},
buttons: buttons,
widget: {
widget: Layout,
options: layout
}
});
}
}
|
Now you can drag the areas around, rearange the layout and even maximize single areas. Let's do one
more thing with the layout before we go further. Beside row
and column
you can define a stack
:
apps/testing-buttons.js
| import { Application, Layout } from "@codecoupler/cc-ui";
import buttons from "./custom-buttons";
import MyFirstWidget from "../widgets/my-first-widget.js";
export default class extends Application {
static ui = {
name: "Testing Buttons",
iconHtml: '<i class="fas fa-seedling fa-fw"></i>'
};
async init() {
let layout = {
header: {
show: true
},
root: {
type: "row",
content: [
{
type: "widget",
title: "Number 1",
widget: MyFirstWidget,
options: {
text: "Hallo Everyone"
}
},
{
type: "column",
content: [
{
type: "widget",
title: "Number 2",
widget: MyFirstWidget,
options: {
text: "How are you?"
}
},
{
type: "stack",
content: [
{
type: "widget",
title: "Number 3",
widget: MyFirstWidget,
options: {
text: "I'm fine, thanks!"
}
},
{
type: "widget",
title: "Number 4",
widget: MyFirstWidget,
options: {
text: "That is amazing!"
}
}
]
}
]
}
]
}
};
await super.init({
panel: {
panelSize: "820 600",
headerTitle: "My First Title",
footerToolbar:
'<i class="far fa-hand-point-right mx-1"></i> [blocks][hints][alerts][close]'
},
buttons: buttons,
widget: {
widget: Layout,
options: layout
}
});
}
}
|
Now you can see the tabs "Number 3" and "Number 4" are "stacked".
Info
To build the layout the library GoldenLayout
in version 2 will be used. The properties
widget
and options
used in CodeCoupler are just alias names for
componentType
amd componentState
. And type = "widget"
is just an alias for type = "component"
.
The layout will always be loaded into the content area of your application. But what if you need to
have a fixed area which cannot be resized?
For this case you have to preload a static HTML structure and define the target container in which a
widget have to be loaded. The structure you define in the property panel.content
(or
panel.contentAjax
/ panel.contentFetch
which will load the content from external sources). The
target element in which the layout have to be loaded must have the attribute data-role="widget"
.
The target container in which the layout widget will be loaded will always emptyed before creating
the layout. So if you specify just panel.content
and no element with the attribute
data-role="widget"
it make no sense. The content would be wiped out.
apps/testing-buttons.js
| import { Application, Layout } from "@codecoupler/cc-ui";
import buttons from "./custom-buttons";
import MyFirstWidget from "../widgets/my-first-widget.js";
export default class extends Application {
static ui = {
name: "Testing Buttons",
iconHtml: '<i class="fas fa-seedling fa-fw"></i>'
};
async init() {
let layout = {
header: {
show: true
},
root: {
/* .... left out for the sake of simplicity .... */
}
};
await super.init({
panel: {
panelSize: "820 600",
headerTitle: "My First Title",
footerToolbar:
'<i class="far fa-hand-point-right mx-1"></i> [blocks][hints][alerts][close]',
content: `
<div class="d-flex flex-column h-100">
<div class="bg-info text-center text-white py-3">+++ Banner +++ Banner +++</div>
<div class="flex-grow-1 position-relative" data-role="widget"></div>
</div>
`
},
buttons: buttons,
widget: {
widget: Layout,
options: layout
}
});
}
}
|
Now you see a banner on top of the layout which will always stay fixed in this position.
Update Layout Size
If you start building content after calling await super.init(...)
it can be that the layout container
gets smaller. In this case the layout will not get notified and you have to do it manually with:
this.layout.updateSize();