Ok override button behavior

Hello everyone.
I’m starting to use the framework and there are certain behaviors that I would like to customize. For example; I like to overwrite the OK button in the edit screen and not close when a new record is created?
It is possible ?, it may be a very simple question but I have searched and have not found anything.
Sorry my bad Enghish.

Regards,
Nelson F

1 Like

First of all, you can use the built-in capability of the platform - extendedWindowActions frame. When you generate standard screens for an entity, select “Extended window actions” checkbox for the editor screen. A quote from the context help:

Extended window actions - if selected, the extendedEditWindowActions frame will be used in the screen instead of editWindowActions. Extended frame contains Save and close, Save and Cancel buttons and enables saving the editor without closing it.

If you already have an editor screen, open it in in Screen Designer, select the existing windowActions frame and just check “extended” on the Properties tab.

If you want full control over the edit screen behavior, better remove windowActions frame from the screen and add custom buttons and handler methods. For example, below is a XML descriptor and controller of an editor that have two buttons. The first button saves if the entity is new and saves and then closes the screen if the entity is not new. The second closes the screen without saving.

<layout expand="hbox"
        spacing="true">
    <fieldGroup id="fieldGroup"
                datasource="customerDs">
        <column width="200px">
            <field id="name"/>
            <field id="email"/>
        </column>
    </fieldGroup>
    <hbox id="hbox"
          spacing="true">
        <button id="okBtn"
                caption="Save"
                invoke="onOkBtnClick"/>
        <button id="cancelBtn"
                caption="Cancel"
                invoke="onCancelBtnClick"/>
    </hbox>
</layout>

public class CustomerEdit extends AbstractEditor<Customer> {
    @Inject
    private Button okBtn;

    @Override
    protected void postInit() {
        if (PersistenceHelper.isNew(getItem())) {
            okBtn.setCaption("Save");
        } else {
            okBtn.setCaption("Save and close");
        }
        setShowSaveNotification(false);
    }

    public void onOkBtnClick(Component source) {
        boolean wasNew = PersistenceHelper.isNew(getItem());
        if (wasNew) {
            // New, just commit
            commit();
        } else {
            // Not new, commit and close
            super.commitAndClose();
        }
    }

    public void onCancelBtnClick(Component source) {
        close(CLOSE_ACTION_ID);
    }
}
1 Like

Thanks for the response, works well, but if I want to create a new record when you click on save ?.
It is to leave the list screen again to enter a new record.

Any ideas or suggestions?

Do you mean the following behaviour:

  1. user clicks New in the browse screen, the edit screen opens
  2. user enters values and clicks Save
  3. a new entity is saved, the editor clears the fields
  4. go to 2
  5. when user clicks Close, the editor screen is closed

If Konstantin is correct, as you describe it is the behavior desired.

It’s an interesting use case. An implementation can be as follows.
First, I created a new editor screen which is registered with ID = demo$Customer.add. It contains custom buttons that invoke handler methods:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<window xmlns="http://schemas.haulmont.com/cuba/window.xsd"
        caption="Multi-create"
        class="com.company.savedemo.web.customer.CustomerAdd"
        datasource="customerDs"
        focusComponent="fieldGroup"
        messagesPack="com.company.savedemo.web.customer">
    <dsContext>
        <datasource id="customerDs"
                    class="com.company.savedemo.entity.Customer" view="_local"/>
    </dsContext>
    <layout expand="hbox" spacing="true">
        <fieldGroup id="fieldGroup"
                    datasource="customerDs">
            <column width="200px">
                <field id="name"/>
                <field id="email"/>
            </column>
        </fieldGroup>
        <hbox id="hbox" spacing="true">
            <button id="saveBtn" caption="Save"
                    invoke="onSaveBtnClick"/>
            <button id="closeBtn" caption="Close"
                    invoke="onCloseBtnClick"/>
        </hbox>
    </layout>
</window>

The editor’s controller:

public class CustomerAdd extends AbstractEditor<Customer> {
    @Inject
    private FieldGroup fieldGroup;
    @Inject
    private Metadata metadata;

    private boolean needRefreshBrowser;

    // indicates for the calling code that we saved some entities
    // and the browser's datasource should be refreshed
    public boolean isNeedRefreshBrowser() {
        return needRefreshBrowser;
    }

    @Override
    public void init(Map<String, Object> params) {
        // remove default actions provided by editor
        removeAllActions();
        // do not show notification on save
        setShowSaveNotification(false);
    }

    public void onSaveBtnClick(Component source) {
        // commit entity
        super.commit();
        // create new instance and set it for the editor
        setItem(metadata.create(Customer.class));
        // set focus to the FieldGroup
        fieldGroup.requestFocus();
        // indicate that we saved some entities
        needRefreshBrowser = true;
    }

    public void onCloseBtnClick(Component source) {
        close(CLOSE_ACTION_ID);
    }
}

In the browse screen, I create an additional Create action in the controller and add a close listener to refresh the datasource if the editor added some entities:

public class CustomerBrowse extends AbstractLookup {
    @Inject
    private Table<Customer> customersTable;
    @Inject
    private CollectionDatasource<Customer, UUID> customersDs;

    @Override
    public void init(Map<String, Object> params) {
        CreateAction multiCreate = new CreateAction(customersTable, WindowManager.OpenType.NEW_TAB, "multiCreate");
        multiCreate.setWindowId("demo$Customer.add");
        multiCreate.setShortcut("ctrl-shift-backslash");
        multiCreate.setCaption("Multi-create");
        multiCreate.setAfterWindowClosedHandler(window -> {
            if (((CustomerAdd) window).isNeedRefreshBrowser()) {
                customersDs.refresh();
            }
        });
        customersTable.addAction(multiCreate);
    }
}
1 Like

Konstantin thank you very much, it worked 100%. It’s an interesting case use, but very useful for when the log entry is quite high.

Thanks again.

Hi
It will be more interesting if it is included in the Studio as an option.

Hi Konstantin,

Is there any simpler way to do this on the “Save” btn, using version 6.1 ?

Hello all together,

that’s exactly the scenario (steps 1…5 mentioned above) I’m struggling with since days, with a slightly different approach: It wouldn’t be suitable to decide in which mode the editor should be opened (single or multi, as proposed above), but open it in one distinct way (‘create’) and decide during editing to save&close or save&create.
I managed those two buttons, the standard behavior, and the one for saving the entity and creating a new instance.
What I’m struggling with is,

  1. how to ‘bind’ the new instance with the editor screen and clear (init) the screen
  2. how to update the lookup after closing the editor screen (have i create the screen programmatically therefore?)

I read the doc’s, saw a couple of solutions for V6.x, but…

Using (as a newby) V 7.2.4

Thank so much for any hint!
Willi