Modal dialog access ClientCallable outside of dialog context?

This is a continuation of this here: https://github.com/vaadin/flow-components/issues/4896#issuecomment-1488801530

Basically I want to have a JS Object in a UI context that allows communication from JS to Java. When a Dialog is Modal, then appearently those calls are blocked (see above).

And setCloseOnOutsideClick function seems to only be applicable when the dialog is in a modal state? So you can’t easily make a dialog non-modal and close it when clicking outside of it…

If I’m not mistaken, this should do it:
@ClientCallable(DisabledUpdateMode.ALWAYS)

Sadly that doesn’t change anything

My current code:

@Tag(Tag.DIV)
    private static class CustomComponent extends Component {
        public CustomComponent() {
        }

        public void roundtrip() {
            getUI().ifPresent(ui -> ui.getPage().executeJs("$0.$server.performAction();", this.getElement()));
        }

        @ClientCallable(DisabledUpdateMode.ALWAYS)
        public void performAction() {
            Notification.show("Roundtrip completed!");
        }
    }
            var dialog = new Dialog();
            CustomComponent myCustomComponent = new CustomComponent();
            UI.getCurrent().add(myCustomComponent);

            var button = new Button("Perform Roundtrip call inside dialog", event -> myCustomComponent.roundtrip());
            dialog.add(button);
            dialog.open();

            layout.add(new Button("Perform Roundtrip call outside dialog", event -> myCustomComponent.roundtrip()));

The only way to make it work seem to be to disable the native vaadin modality of the dialog and emulate the close on exit behavior with a fullscreen transparent overlay that captures all mouse clicks outside the dialog

Just in case someone else reads this, Knoobie suggested to use ``@AllowInert` which works.

Modal dialog access ClientCallable outside of dialog context?

From internal package :grimacing:

That is most likely a design flaw. Even if disabled and “disabled by modality” components would need to be separated, there would be plenty of room for more enums in the current parameter for clientcallable. Probably the implementor of the modality curtain didn’t know about the parameter…

To be honest, I think it would help if at least there were some log messages when calls were blocked due to the modality curtain. The whole feature is somewhat hidden in the documentation, and I think there should be a clear indication what is happening and how to fix it.

Also I wonder where those calls go? Because the javascript Promises never complete… No exception, no attached handler is executed, nothing

If the calls get blocked, the least I’d expect would be a cancelation/exception from the promise, but there is nothing

e.$server.callToJava()
                    .then(() => {
                        ...
                    }).catch((error) => {
                        ...
                    }).finally(() => {
                        ...
                    });

I’d expect at least the ‘finally’ block to execute, and either the ‘then’ or ‘catch’ block

but the modality curtain simply swallows the call, and nothing is executed, even after the modality scenerio resolves. Basically the API breaks its ‘Promise’ :wink:

Thinking about it from a security point of view (as the server-side modality curtain is a security feature), attempting to call a ClientCallable method which is not available at the current modality level should behave the same as a non-existent method

although this might not be feasible, as the generated JavaScript function already exists in the client

Depends how it’s implemented, I assume the “$server” property calls some getter, if that returned $server object is individual for each modal context, it could work

and then there would be at least a traceable error in the javascript log