Can a Single Entity Editor update 2 different entities

Hello Team,

Is there a known way to update 2 different entities from a single editor, the example is as following:

  • I Have an entity called Customer that has the following attributes:
  1. Name : String
  2. Birth Date : Date
  3. Currency : String
  • I Have another entity called CustomerLocation that has the following attributes which are updated from a different editor:
    1.Customer : Reference
    2.Address : String
    3.Contact : String
    4.Main Location : Boolean

Only one location can be marked as main location for a single customer, is there a way to virtually have single editor called Customer with the following attributes:

  1. Name: String
  2. Birth Date: Date
  3. Currency: String
  4. Address : String
  5. Contact: String

the user will primary use the new editor to insert/update customers and updates the customer main location, and in minor cases the user will still use the CustomerLocation Editor only if a particular customer have multiple locations.

In the backend of the virtual editor, i want to insert/update a customer and insert/update a main customer location.

my question is, can i do this type of editor in Cuba and how?

Hi Tarek!

Yes, you can do it. There is a sample project with new CUBA 7 screens. But pay attention, that there is no any consistency checks of the model, only the screens.

First of all, look at editor screen descriptor. It uses two data containers, one for Customer and one for CustomerLocation. locationDc is a collectionContainer as the Customer can have not any location (or you need strong consistency checks otherwise).
The data is displayed with a form component. I specified main form data container and locationDc as data container for address and contanct fields.

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<window xmlns="http://schemas.haulmont.com/cuba/screen/window.xsd"
        xmlns:c="http://schemas.haulmont.com/cuba/screen/jpql_condition.xsd"
        caption="msg://editorCaption"
        focusComponent="form"
        messagesPack="com.company.untitled8.web.entity.customer">
    <data>
        <instance id="customerDc"
                  class="com.company.untitled8.entity.Customer"
                  view="_local">
            <loader id="customerDl"/>
        </instance>

        <collection id="locationDc"
                  class="com.company.untitled8.entity.CustomerLocation"
                  view="customerLocation-view">
            <loader id="locationDl">
                <query><![CDATA[select l from untitled8_CustomerLocation l]]>
                    <condition>
                        <and>
                            <c:jpql>
                                <c:where>l.mainLocation = TRUE</c:where>
                            </c:jpql>
                            <c:jpql>
                                <c:where>l.customer = :customer</c:where>
                            </c:jpql>
                        </and>
                    </condition>
                </query>
            </loader>
        </collection>
    </data>
    <dialogMode height="600"
                width="800"/>
    <layout expand="editActions" spacing="true">
        <form id="form" dataContainer="customerDc">
            <column width="250px">
                <textField id="nameField" property="name"/>
                <textField id="birthDateField" property="birthDate"/>
                <textField id="currencyField" property="currency"/>
                <textField dataContainer="locationDc" property="address"/>
                <textField dataContainer="locationDc" property="contact"/>
            </column>
        </form>
        <hbox id="editActions" spacing="true">
            <button action="windowCommitAndClose"/>
            <button action="windowClose"/>
        </hbox>
    </layout>
</window>

Now, look at screen controller.

@UiController("untitled8_Customer.edit")
@UiDescriptor("customer-edit.xml")
@EditedEntityContainer("customerDc")
//@LoadDataBeforeShow - pay attention, that this annotation is absent. Studio generates it by default
public class CustomerEdit extends StandardEditor<Customer> {

    @Inject
    private CollectionContainer<CustomerLocation> locationDc;
    @Inject
    private CollectionLoader<CustomerLocation> locationDl;
    @Inject
    private InstanceLoader<Customer> customerDl;

    @Inject
    private Metadata metadata;
    @Inject
    private DataContext dataContext;

    @Subscribe
    private void onBeforeShow(BeforeShowEvent event) {
//        Load editing customer before show
        customerDl.load();
    }

    @Subscribe(id = "customerDc", target = Target.DATA_CONTAINER)
    private void onCustomerDcItemChange(InstanceContainer.ItemChangeEvent<Customer> event) {
        Customer customer = event.getItem();

//        bind :customer parameter of locationDl to editing customer
        locationDl.setParameter("customer", customer);
        locationDl.load();
    }

    @Subscribe(id = "locationDc", target = Target.DATA_CONTAINER)
    private void onLocationDcCollectionChange(CollectionContainer.CollectionChangeEvent<CustomerLocation> event) {
//        when locationDc refreshed, choose first loaded item or create new one
        if (event.getChangeType() == CollectionChangeType.REFRESH) {
            if (!locationDc.getItems().isEmpty()) {
                locationDc.setItem(locationDc.getItems().get(0));
            } else {
                locationDc.setItems(Collections.singleton(createMainLocation(getEditedEntity())));
            }
        }
    }

    /**
     * Creating new main location for customer
     */
    private CustomerLocation createMainLocation(Customer customer) {
        CustomerLocation customerLocation = metadata.create(CustomerLocation.class);
        customerLocation.setCustomer(customer);
        customerLocation.setMainLocation(true);
        return dataContext.merge(customerLocation);
    }
}

Also you can download a whole project.
untitled8.zip (88.7 KB)