Hi,
I want users to select some shortcuts from the side menu. Now, the available menu items differ and are partly created dynamically (not only in web-menu.xml).
I would like to provide a tree selector with their menu shown as items and have therefore created a custom value datasource based on a non-persistent entity that resembles the menu items:
@NamePattern("%s|caption")
@MetaClass(name = "base$MenuEntity")
public class MenuEntity extends BaseStringIdEntity implements HasUuid {
private static final long serialVersionUID = 4397712108622636264L;
@Id
@MetaProperty(mandatory = true)
protected String id;
@MetaProperty
protected UUID uuid;
@MetaProperty
protected String caption;
@MetaProperty
protected MenuEntity parent;
// continues with all getters and setters ...
}
The custom datasource:
public class MenuItemDatasource extends CustomValueHierarchicalDatasource {
private HashMap<String, MenuEntity> menuItems;
/**
* Custom method to pass side menu as a list of values
*/
private void addMenuItems(MenuEntity parent, List<SideMenu.MenuItem> children) {
// Fill collection with information
children.forEach(i -> {
MenuEntity m = metadata.create(MenuEntity.class);
m.setCaption(i.getCaption());
m.setId(i.getId());
m.setParent(parent);
menuItems.put(m.getId(), m);
// Parse the tree
if (i.getChildren() != null)
addMenuItems(m, i.getChildren());
});
}
/**
* Simply return the list with menu items
*/
@Override
protected Collection<KeyValueEntity> getEntities(Map<String, Object> params) {
// Initialise (or clear) current collection
menuItems = new HashMap<>();
// Create a root entry and add it to the set
MenuEntity root = metadata.create(MenuEntity.class);
root.setCaption("root");
root.setId("root");
root.setParent(null);
menuItems.put(root.getId(), root);
// Process the list of menu items
ExtAppMainWindow mainWindow = (ExtAppMainWindow) AppUI.getCurrent().getTopLevelWindow();
addMenuItems(root, mainWindow.getSideMenu().getMenuItems());
// Transform into collection
Collection<KeyValueEntity> items = new ArrayList<>();
menuItems.forEach((id, m) -> {
KeyValueEntity e = new KeyValueEntity();
e.setIdName("id");
e.setMetaClass(metadata.getClass(MenuEntity.class));
e.setId(id);
e.setValue(m.getCaption(), m);
});
return items;
}
}
When I use this datasource in a screen, it is loaded correctly but not shown in the tree component.
<dsContext>
<valueHierarchicalDatasource id="menuItemsDs"
hierarchyProperty="parent"
datasourceClass="com.company.app.web.general.MenuItemDatasource">
<properties idProperty="id">
<property name="id" datatype="string"/>
<property name="caption" datatype="string"/>
<property name="parent" class="com.company.app.general.MenuEntity"/>
</properties>
</valueHierarchicalDatasource>
</dsContext>
<!-- layout definition -->
<tree id="menuSelection" width="500px">
<treechildren datasource="menuItemsDs" captionProperty="caption" hierarchyProperty="parent"/>
</tree>
And in the controller:
@Inject
private ValueHierarchicalDatasourceImpl menuItemsDs;
@Inject
private Tree<MenuEntity> menuSelection;
@Override
public void postInit() {
super.postInit();
// Refresh datasource
menuItemsDs.refresh();
// Let something happen when clicked
menuSelection.setItemClickAction(new BaseAction("treeClickAction")
.withHandler(actionPerformedEvent -> {
MenuEntity item = menuSelection.getSingleSelected();
if (item != null) {
showNotification(item.getId());
}
}));
}
Any ideas why the tree component remains empty? The datasource holds the items and all the data seems ok.
Thanks for help or any suggestions.
-b