Laying out your dialogs
Tabbed layout
If you need your dialog split in meaningful sections, tabs are probably the most common way to do the task. There can be reasons to create a tabbed dialog even if a single section would be sufficient. That's because the tab would have a title that would additionally hint at the dialog settings' role (something like "General config").
There are several ways to create tabbed dialogs. First, you may need to mark a nested class of your @Dialog
-annotated class with @Tab
annotation. The title property of @Tab
will be used as the tab's node name and non-alphanumeric characters will be skipped (for example, @Tab(title="First tab title!")
will produce <firstTabTitle> tag)
@Dialog
public class Dialog {
@Tab(title = "First tab")
static class Tab1 {
@DialogField(label="Field in the first tab")
@TextField
String field1;
}
@Tab(title = "Second tab")
static class Tab2 {
@DialogField(label="Field in the second tab")
@TextField
String field2;
}
}
The other way of laying out tabs is to define an array of @Tab
within @Tabs
annotation attached to the dialog file. Then, to settle a field to a certain tab you will need to add @Place
annotation to this particular field. The values of @Place
must correspond to the value of the desired tab. This is a somewhat more flexible technique which avoids creating nested classes and allows freely moving fields (same as for @AccordionPanel
). But please ensure that the tab title is specified everywhere in the same format.
@AemComponent(
path= "path/to/my/component",
title = "My Component Dialog"
)
@Dialog
@Tabs({
@Tab(title = "First tab"),
@Tab(title = "Second tab"),
@Tab(title = "Third tab")
})
public class MyComponent {
@DialogField(label = "Field in the first tab")
@TextField
@PlaceOn("First tab")
String field1;
@DialogField(label = "Field in the second tab")
@TextField
@PlaceOn("Second tab")
String field2;
@DialogField(description = "Field in the third tab")
@TextField
@PlaceOn("Third tab")
String field3;
}
Tabs declared this way are virtually "inherited" from a superclass to a descendant class. The following setup is valid:
@Tabs({
@Tab(title = "First tab"),
@Tab(title = "Second tab")
})
public class MyComponentAncestor {/* ... */}
@AemComponent(
path= "path/to/my/component",
title = "My Component Dialog"
)
@Dialog
@Tabs(@Tab(title = "Third tab"))
public class MyComponent extends MyComponentAncestor {
@DialogField(label = "Field in the first tab")
@TextField
@PlaceOn("First tab")
String field1;
}
Note that the ancestor class does not have to be declared @AemComponent
itself (however may as well stand as a separate entity). If not every tab present in an ancestor needs to be rendered in a child, the child class can have @Ignore(sections = "Tab from ancestor")
attached. See more on this in Reusing code and making it brief, the "Sections inheritance" division.
Additionally, you can facilitate a tabbed area within the dialog or one of its sections to keep your visual elements well organized. See the "Tabs" division in Component Structure for particulars.
Accordion layout
- @Accordion
- Resource type: /libs/granite/ui/components/coral/foundation/accordion
- See spec: Accordion
Creating an accordion is also a widely used way to arrange multiple components within a dialog or a dialog section. This is done with the use of @Accordion
annotation.
Same as for the tabs, the @Accordion
annotation can be exploited in two different ways. If added to a Java class itself, it manifests that the whole dialog will be laid out in accordion style, but if added to a particular field or method, it creates a nested accordion within the dialog.
In both cases, @Accordion
bears an array of @AccordionPanel
s defined by their titles To settle a field to a certain accordionPanel, you will need to add a @Place
annotation to this particular field. The values of @Place
must correspond to the value of the desired panel.
The other way to create a panel is to declare a nested class annotated with @AccordionPanel
. You only need to ensure that the panel title is specified everywhere in the exact same format with no extra spaces, etc.
@AemComponent(
path= "path/to/my/component",
title = "My Component Dialog"
)
@Dialog
@Accordion({
@AccordionPanel(title = "First panel"),
@AccordionPanel(title = "Second panel")
})
public class MyComponent {
@DialogField(label = "Field in the first panel")
@TextField
@Place("First panel")
String field1;
@DialogField(label = "Field in the second panel")
@TextField
@Place("Second panel")
String field2;
}
Accordion panels inheritance and ignoring works exactly the same as for the tabs. And so is the ability to create a nested accordion within a dialog or its section. See the "Accordion" division in Component Structure.
Fixed columns layout
- @FixedColumns
- Resource type: /libs/granite/ui/components/foundation/layouts/fixedcolumns
- See spec: FixedColumns
Fixed columns are the default layout for a Granite UI dialog unless some specific one, such as Tabs or Accordion, is requested. By default, it creates a single fixed-width column.
Most of the time you wouldn't need to specify it at all. Still, you might want to, and it is when more than one column is required.
@AemComponent(
path= "path/to/my/component",
title = "My Component Dialog"
)
@Dialog
@FixedColumns({
@Column(title = "First"),
@Column(title = "Second")
})
public class MyComponent {
@DialogField(label = "Field in the first column")
@TextField
@Place("First")
String field1;
@DialogField(label = "Field in the second column")
@TextField
@Place("Second")
String field2;
}
Multiple columns are placed side-by-side if the width of the dialog allows, or else go one under the other. Please note that the title is not rendered in the UI; it is used for merely referring to a particular column in @Place(...)
.
Then again, same as for Tabs and Accordion, @FixedColumns
can be used as an in-dialog widget. This is particularly useful when you need to render dialog content screen-centered, as within a Page properties' tab (see "Page properties" section in Component Structure). For the in-dialog usage two additional properties of @FixedColumns
can be specified: margin and maximized (see the Javadoc for more detail).