-
Notifications
You must be signed in to change notification settings - Fork 44
Vaadin 8 | Dynamic Initalization
appreciated edited this page Jun 25, 2018
·
1 revision
On the first glance it might look like the AppLayout
cannot be configured with dynamic content.
In fact it is actually possible to do so. If you don't build the AppLayout
right away but instead keep the instance of the AppLayoutBuilder
(But remember to build it before adding it to the UI / Layout). This allows you to call the add
method dynamically from other places.
Note: The same applies to the SubmenuBuilder.
@Override
protected void init(VaadinRequest vaadinRequest) {
// Build there lists any way (f.e. dynamically) you want
List<MenuItem> myDynamicSubmenu1 = Arrays.asList(
new MenuItem("View2", VaadinIcons.ABACUS, View2.class),
new MenuItem("View3", VaadinIcons.ABACUS, View3.class)
);
List<MenuItem> myDynamicSubmenu2 = Arrays.asList(
new MenuItem("View4", VaadinIcons.ABACUS, View4.class),
new MenuItem("View5", VaadinIcons.ABACUS, View5.class)
);
AppLayoutBuilder builder = AppLayoutBuilder.get(Behaviour.LEFT_RESPONSIVE_HYBRID)
.withTitle("My Title")
.withDesign(AppBarDesign.MATERIAL)
.withDefaultNavigationView(MyDefaultView.class)
.add(new MenuHeader("My Title", new ThemeResource("icon.png")))
.add("View1", VaadinIcons.ABACUS, View1.class);
SubmenuBuilder submenu1 = SubmenuBuilder.get("Submenu1", VaadinIcons.FILE_TREE);
myDynamicSubmenu1.forEach(item -> submenu1.add(item.name, item.icon, item.viewClass));
builder.add(submenu1.build());
SubmenuBuilder submenu2 = SubmenuBuilder.get("Submenu2", VaadinIcons.FILE_TREE);
myDynamicSubmenu1.forEach(item -> submenu1.add(item.name, item.icon, item.viewClass));
builder.add(submenu2.build());
setContent(builder.build());
}
class MenuItem {
String name;
Resource icon;
Class<View> viewClass;
MenuItem(String name, Resource icon, Class<View> viewClass) {
this.name = name;
this.icon = icon;
this.viewClass = viewClass;
}
}
Note: Replace MenuItem with your own entity.
You might have the problem that you already have a menu structure but don't know how to translate it into this menu. Here is an example how it can be done:
@Override
protected void init(VaadinRequest vaadinRequest) {
// Build this tree any way (f.e. dynamically) you want
List<MenuItem> items = Arrays.asList(
new MenuItem("View1", VaadinIcons.ABACUS, View1.class),
new MenuItem("Submenu", VaadinIcons.FILE_TREE, Arrays.asList(
new MenuItem("SubmenuItem 1", VaadinIcons.ACADEMY_CAP, View2.class),
new MenuItem("SubmenuItem 2", VaadinIcons.ACADEMY_CAP, View3.class),
new MenuItem("SubmenuItem 3", VaadinIcons.ACADEMY_CAP, View4.class)
)),
new MenuItem("View1", VaadinIcons.ABACUS, View5.class)
);
AppLayoutBuilder builder = AppLayoutBuilder.get(Behaviour.LEFT_RESPONSIVE_HYBRID)
.withTitle("My Title")
.withDesign(AppBarDesign.MATERIAL)
.withDefaultNavigationView(MyDefaultView.class)
.add(new MenuHeader("My Title", new ThemeResource("icon.png")));
items.forEach(menuItem -> {
if (menuItem.hasSubItems()) {
SubmenuBuilder submenuBuilder = SubmenuBuilder.get(menuItem.name, menuItem.icon);
menuItem.subItems.forEach(item -> addSubMenuItem(submenuBuilder, item));
builder.add(submenuBuilder.build());
} else {
builder.add(menuItem.name, menuItem.icon, menuItem.viewClass);
}
}
);
setContent(builder.build());
}
private void addSubMenuItem(SubmenuBuilder builder, MenuItem item) {
if (item.hasSubItems()) { // if the item still has children -> recursion
SubmenuBuilder submenuBuilder = SubmenuBuilder.get(item.name, item.icon);
item.subItems.forEach(subItem -> addSubMenuItem(submenuBuilder, subItem));
builder.add(submenuBuilder.build());
} else {
builder.add(item.name, item.icon, item.viewClass);
}
}
// incomplete `Composite pattern` which is used to represent your menu element tree
class MenuItem {
String name;
Resource icon;
Class<View> viewClass;
List<MenuItem> subItems = null;
MenuItem(String name, Resource icon, Class<View> viewClass) {
this(name, icon, (List<MenuItem>) null);
this.viewClass = viewClass;
}
MenuItem(String name, Resource icon, List<MenuItem> subItems) {
this.name = name;
this.icon = icon;
this.subItems = subItems;
}
boolean hasSubItems() {
return subItems != null;
}
}
Note: Replace MenuItem with your own entity.