Please note that your entire codebase should work on the new version of the framework only with minor changes listed in the release notes, i.e. you don’t need to migrate existing screens on the new API, but if you want, the following guide may be helpful.
Table of Contents
Migration to CUBA 7 API: Screens
Migration to CUBA 7 API: Browser / Lookup Screens
Migration to CUBA 7 API: Editor Screens
Migration to CUBA 7 API: Required Components Migration
Migration to CUBA 7 API: Optional Components Migration
The invoke
attribute
XML elements such as <button>
and <action>
have the invoke
attribute, which must be replaced by the corresponding component subscription, e.g.
Before
XML
...
<actions>
<action id="someAction"
caption="Click Me!"
invoke="someAction"/>
</actions>
...
<button caption="Say Hello!"
description="Click Me!"
invoke="sayHello"/>
...
Controller
public void someAction() {
...
}
public void sayHello() {
...
}
After
XML
...
<actions>
<action id="someAction"
caption="Click Me!"/>
</actions>
...
<button id="helloButton"
caption="Say Hello!"
description="Click Me!"/>
...
Controller
@Subscribe("someAction")
protected void onSomeActionActionPerformed(Action.ActionPerformedEvent event) {
...
}
@Subscribe("helloButton")
protected void onHelloButtonClick(Button.ClickEvent event) {
...
}
Bulk Editing
Replace the bulkEditor
component with the bulkEdit
action.
Before
<buttonsPanel>
<bulkEditor for="customersTable"/>
</buttonsPanel>
After
...
<actions>
<action id="bulkEdit" type="bulkEdit"/>
</actions>
...
<buttonsPanel>
<button id="bulkEditButton"
action="customersTable.bulkEdit"/>
</buttonsPanel>
...
CollectionContainer Add/Remove items
In order to mutate CollectionContainer
items (similar to CollectionDatasource addItem()
/ removeItem()
), the getMutableItems()
method must be used.
getMutableItems()
- returns a mutable list of entities stored in the container. All list changes caused by the add()
, addAll()
, remove()
, removeAll()
, set()
, clear()
methods produce CollectionChangeEvent
, so subscribed visual components will update accordingly.
Before
customersDs.addItem(newCustomer);
After
customersDc.getMutableItems().add(newCustomer);
Component type parameters
It is highly recommended to set type parameter for UI components explicitly, even default type parameter should be set. For example:
@Inject
protected LookupField<User> userField;
@Inject
protected TextField<Long> countField;
@Inject
protected Label<String> defaultTypedLabel;
Create/Edit actions with OpenType.DIALOG
Standard actions ignore the openType
attribute which is taken into account by legacy actions.
For the new API, you need to subscribe on ActionPerformedEvent and provide a custom implementation, e.g.
@UiController("sales_Product.browse")
@UiDescriptor("product-browse.xml")
@LookupComponent("productsTable")
@LoadDataBeforeShow
public class ProductBrowse extends StandardLookup<Product> {
@Inject
private GroupTable<Product> productsTable;
@Inject
private ScreenBuilders screenBuilders;
@Subscribe("productsTable.create")
private void onProductsTableCreate(Action.ActionPerformedEvent event) {
screenBuilders.editor(Product.class, this)
.newEntity()
.withLaunchMode(OpenMode.DIALOG)
.build()
.show();
}
@Subscribe("productsTable.edit")
private void onProductsTableEdit(Action.ActionPerformedEvent event) {
screenBuilders.editor(productsTable)
.withLaunchMode(OpenMode.DIALOG)
.build()
.show();
}
}
The easiest way is to set forceDialog="true"
for the <dialogMode/>
element of an editor screen.
<dialogMode height="600"
width="800"
forceDialog="true"/>
The third possible approach is to implement custom Create/Edit actions that can be used independently of the standard ones.
This demo project illustrates the above dialog-actions.zip (81.7 KB).
DialogCreateAction
and DialogEditAction
are custom actions and both are used in the product-browse.xml
:
@ActionType(DialogCreateAction.ID)
public class DialogCreateAction extends CreateAction {
public static final String ID = "create_dialog";
public DialogCreateAction() {
this(ID);
}
public DialogCreateAction(String id) {
super(id);
}
@SuppressWarnings("unchecked")
@Override
public void actionPerform(Component component) {
// if standard behaviour
if (!hasSubscriptions(ActionPerformedEvent.class)) {
Screen editor = screenBuilders.editor(target)
.newEntity()
.withOpenMode(OpenMode.DIALOG)
.build();
editor.show();
} else {
super.actionPerform(component);
}
}
}
@ActionType(DialogEditAction.ID)
public class DialogEditAction extends EditAction {
public static final String ID = "edit_dialog";
public DialogEditAction() {
super(ID);
}
public DialogEditAction(String id) {
super(id);
}
@SuppressWarnings("unchecked")
@Override
public void actionPerform(Component component) {
// if standard behaviour
if (!hasSubscriptions(ActionPerformedEvent.class)) {
Entity editedEntity = target.getSingleSelected();
Screen editor = screenBuilders.editor(target)
.editEntity(editedEntity)
.withOpenMode(OpenMode.DIALOG)
.build();
editor.show();
} else {
super.actionPerform(component);
}
}
}
<actions>
<action id="create" type="create_dialog"/>
<action id="edit" type="edit_dialog"/>
...
</actions>
Similarly to screens, the actions base package must be registered in the web-springs.xml
<gui:actions base-packages="com.company.demo.gui.actions"/>
Query parameters
Using Screen Parameters in Loaders
Dependencies Between Data Components