Hi, I’ve just started out on CUBA development and I’ve got stuck on a feature I’m trying to implement.
Based on data that a user creates at runtime, I’m trying to create a dynamic screen to edit that data. The closest I’ve come to based on your documentation is to use the KeyValueEntitiy class. Here is my non-working code to create a sample KeyValueEntitiy and edit it:
I created a screen in the designer for the KeyValueEntity class and called the screen KeyValueEntityEdit. Property1 and Property2 could be any number of properties defined at run time. I don’t want a table to edit the properties, but rather individual edit fields as there won’t be a large number, so one screen to edit all properties.
It doesn’t work as I get an access denied message. I’m guessing my code is far too simplistic and that I have to somehow configure metadata in some way, but I’m stuck.
Have you got a simple example to achieve the above? Or even better could I create a non-persistent entity and an associated screen at run time? Again an example of this would be great.
Hi Support, would you be able to help with the above problem of creating a screen at run time for a KeyValueEntity. I’m currently using an InputDialog with parameters but I’d like to be able to “style” the screen using, for example, hbox and vbox components.
I’m glad the question is still actual for you, I came across it today and have just prepared an example.
I’ve created two screens - Browse and Edit, both extend the simple Screen and are not linked to entities in the standard way.
The Browser allows users to view key-value entities with two fields and create new ones by calling the editor.
@UiController("kvdemo_EditScreen")
@UiDescriptor("edit-screen.xml")
public class EditScreen extends Screen {
@Inject
private VBoxLayout fieldsBox;
@Inject
private UiComponents uiComponents;
private KeyValueContainer container;
public KeyValueContainer getContainer() {
return container;
}
public void setContainer(KeyValueContainer container) {
this.container = container;
}
@Subscribe
public void onBeforeShow(BeforeShowEvent event) {
for (MetaProperty metaProperty : container.getEntityMetaClass().getProperties()) {
Field field;
if (metaProperty.getJavaType().equals(String.class) || metaProperty.getJavaType().equals(Integer.class)) {
field = uiComponents.create(TextField.class);
} else {
throw new UnsupportedOperationException("Unsupported type");
}
field.setValueSource(new ContainerValueSource<>(container, metaProperty.getName()));
fieldsBox.add(field);
}
}
@Subscribe("okBtn")
public void onOkBtnClick(Button.ClickEvent event) {
close(StandardOutcome.COMMIT);
}
}
As you can see, I programmatically create data containers and visual components for working with key-value entities having arbitrary fields. The data containers know the structure of key-value entities (they create an appropriate MetaClass under the hood) from addProperty() calls, so it’s convenient to pass to the editor not the entity itself but the data container with the entity.
See the entire project attached. kvdemo.zip (83.5 KB)
Thank you Konstantin, I’ve written a sample based on your reply and it works great thank you.
Out of interest, for simple editing of a KeyValueEntity is it not possible to use a KeyValueEntityEditor without getting the access denied error? In the UI you do offer this type of entity as an option for EntityEditor creation.
In fact, StandardEditor cannot work with KeyValueEntity, you get “access denied” exception probably because the editor tries to reload the entity from the database. It’s a bug that Studio offers KeyValueEntity in the edit screen, I’ll file an issue for this.