Templates in Shui are trees of elements that are created only on demand.
Some elements that spawn children dynamically make use of templates.
The Repeater element, for instance, creates a number of child
elements by applying a template assigned to the delegate
property
according to a list model.
Templates must be marked with the template
keyword.
Document {
Repeater {
model: ListModel {
// have three children
data: sequence(0, 3)
}
// the template describes what the children look like
delegate: template Label {
text: "A label"
}
}
}
Templates are Functions
Technically, a template is a function that creates and returns a tree of elements when invoked. You may assign templates to properties and call them directly in JavaScript blocks.
This example adds a dropdown menu to a button.
require "shellfish/ui"; // we are using some elements from this module
Document {
Button {
property menuT: template Menu {
MenuItem { text: "Item A" }
MenuItem { text: "Item B" }
}
text: "Click Me"
onClick: () =>
{
// create the menu from the template when the button is clicked
const menu = menuT();
// show the menu next to the button
menu.popup(self);
}
}
}
Templates are Components
Templates behave like components. This means they form their own scope for element identifiers. Element identifiers defined inside a template are not accessible from outside. On the other hand, element identifiers defined outside the template may be accessed by the template, as the template itself is in the scope of where it (the template) was defined.
Document {
Repeater {
model: ListModel {
data: sequence(0, 3)
}
delegate: template Box {
Label {
id: innerLabel
// THIS IS OK: outerBox is visible to the template
text: "Contains Mouse: " + outerBox.containsMouse
}
}
}
MouseBox {
id: outerBox
width: 100
height: 100
color: "red"
onClick: () =>
{
// THIS DOES NOT WORK: innerLabel is not visible outside the template
//innerLabel.text = "Does not work!";
}
}
}
Note: If you try this example, you will notice that the Label
elements appear underneath
the MouseBox
, even though the Repeater
is placed before it. Why is this so?
The repeater is an abstract element that puts the spawned child elements into its
parent container. This will be explained later in Defered Creation of UI Elements.