Ask user to validate before commit

CUBA 6.10
Suppose you have some fields of an entity representing a state that is invalid under certain circumstances, but you want to ask the user for confirmation right before commit or as soon as such state is reached.
What’s the easiest way to achieve this?
The way I managed to solve the problem - though I’m not sure is the right way to go - is to create a wrapper class around the ‘OK’ button action.
Code in the following, where violatingFiled is the field whose value needs confirmation and validateMyFields() is the method that will return true if the filed is valid and no question is to be asked

public class MyEdit extends AbstractEditor<MyEntity> {
    @Named("filedGroup.violatingField")
    private Field violatingField;

    protected void postInit() {
    super.postInit();

    // Set Wrappers for Save Save&Close
    Button commitAndCloseBtn = ((Button) getWrappedWindow().getComponent("windowCommitAndClose"));
    Button commitBtn = ((Button) getWrappedWindow().getComponent("windowCommit"));
    if (commitAndCloseBtn!=null) {
        commitAndCloseBtn.setAction(new BaseActionWrapper((BaseAction) commitAndCloseBtn.getAction()));}
    if (commitBtn!=null) {
        commitBtn.setAction(new BaseActionWrapper((BaseAction) commitBtn.getAction()));}
    }
    
    private class BaseActionWrapper extends BaseAction{
    private BaseAction myAction;

    public BaseActionWrapper(BaseAction action) {
        super(action.getId().concat("Wrapper"));
        myAction = action;
    }

    @Override
    public String getCaption() {
        return myAction.getCaption();
    }

    @Override
    public void actionPerform(Component component) {
        if (validateMyFields()) {myAction.actionPerform(component); return;}

        DialogAction confirmAction = new DialogAction(DialogAction.Type.YES, Action.Status.PRIMARY);
        confirmAction.withHandler(e -> myAction.actionPerform(component));
        confirmAction.setCaption(getMessage("okBtnCaption"));
        DialogAction modifyAction = new DialogAction(DialogAction.Type.NO, Action.Status.NORMAL);
        modifyAction.setCaption(getMessage("modifyBtnCaption"));
        modifyAction.setIcon("font-icon:PENCIL");
        modifyAction.withHandler(e -> {violatingField.setValue(ViolatingFiledType.safe);
        myAction.actionPerform(component);});

        showOptionDialog(getMessage("confirmTitle"), getMessage("confirmMessage"),
                MessageType.CONFIRMATION.modal(true), new Action[]{confirmAction, modifyAction});
    }
}

private boolean validateMyFields() {return false;}
}

For version 6, The simplest way to interact with the user on screen commit is explained in this topic. In your case it should be something like this:

public class MyEdit extends AbstractEditor<MyEntity> {

    @Override
    public void commitAndClose() {
        if (!validateMyFields()) {
            showOptionDialog(
                    "Confirm",
                    "Are you sure you want to save changes?",
                    MessageType.CONFIRMATION,
                    new Action[] {
                            new DialogAction(DialogAction.Type.YES) {
                                @Override
                                public void actionPerform(Component component) {
                                    CustomerEdit.super.commitAndClose();
                                }
                            },
                            new DialogAction(DialogAction.Type.NO)
                    }
            );
        }
    }

    private boolean validateMyFields() {
        return false;
    }
}

In version 7.0+, use BeforeCommitChangesEvent.

1 Like

That’s better! Thank you