is there any way to abort closing a (sub)window in a window’s close listener? In my case I would like to abort in case of unsaved modifications.
I would like to keep the close button in the upper-right corner of the window enabled because most users are used to close windows in Windows by clicking that button.
Check the source of the Window class. it has a function called close() which is protected. This function takes care of the removing of windows. It has a nice javadoc describing how you can attach a closeListener, the listener you already mentioned, to do fancy stuff. I’m myself not directly familiar with this listener, so I would just override the function close() to do my own check first.
Window mySubWindow = new Window(){
protected void close() {
if(isAllowedToCloseWindow()){
super.close();
} else{
getMainWindow().showNotification("Don't close me!");
}
};
};
you can change that isAllowedToCloseWindow() to some check to see if there is some unsaved data.
I need to have a confirmation box stating do you need to save before closing when i close a browser . It is a browser level close and not a subwindow. please help me out on how to get a confirmation box on browser close .
Redux: It is only possible by creating a new Vaadin Widget. However, I did this recently for my work project, and I’ll share my code below. Sorry, I don’t really have time to publish this in the Vaadin Directory: there should be guidance in the Book of Vaadin on how to build/compile/include Widgets in your vaadin widgetset.
Cheers,
Charles.
/**
* The exit notifier is an invisible widget which, when a user attempts to leave a page, will display a confirmation dialog
* containing the message as set by {@link #setMessage(String)}
*
* <p/>
*
* This message is displayed and controlled by the browser; the precise content and style of the window is controlled
* by the browser itself, will between different between different browser, and *cannot* be prettified and/or otherwise
* improved.
* <p/>
* Based on code from https://vaadin.com/forum/-/message_boards/view_message/44668
* <p/>
* Note that the message is only displayed if <br/>
* a) The main portion of the URL changes (i.e. *before* the URI Fragment/# symbol) <br/>
* b) The browser tab/window is closed. <br/>
*
*/
@ClientWidget(VExitNotifier.class)
public class ExitNotifier extends AbstractComponent {
private static final long serialVersionUID = 7448235866025390836L;
protected String message;
public ExitNotifier() {
}
public ExitNotifier(String message) {
setMessage(message);
}
public void paintContent(PaintTarget t) throws PaintException {
super.paintContent(t);
t.addAttribute("message", Strings.nullToEmpty(message));
}
/**
* The message that will be displayed.
* @return
*/
public String getMessage() {
return message;
}
/**
* The message to display on the confirmation dialog box when the user tries to leave the current page.
* If null or empty, no confirmation dialog will be displayed.
*
* @param message
*/
public void setMessage(String message) {
this.message = message;
requestRepaint();
}
}
public class VExitNotifier extends SimplePanel implements Paintable {
private HandlerRegistration handlerRegistration;
private String message;
public VExitNotifier() {
getElement().getStyle().setDisplay(Style.Display.NONE);
}
@Override
public void updateFromUIDL(UIDL uidl, ApplicationConnection client) {
String message = uidl.getStringAttribute("message");
this.message = (message == null || message.trim().length() == 0) ? null : message;
}
public void onLoad() {
this.handlerRegistration = Window.addWindowClosingHandler(new Window.ClosingHandler() {
@Override
public void onWindowClosing(Window.ClosingEvent event) {
event.setMessage(message);
}
});
}
public void onUnload() {
handlerRegistration.removeHandler();
}
}
Hi all, here is my solution, which is an extension of what Charles has proposed. Unfortunately at this point of time the solution above uses depricated interface “Paintable” so I have simple created a simple Vaadin component with connector and it’s state. Here i have a question to those more experienced: Is it a correct solution or is there a “less classes” method?
Component:
package com.infosystem.widgets.vaadin;
import com.infosystem.widgets.vaadin.client.gwt.exitNotifier.ExitNotifierState;
import com.vaadin.ui.AbstractComponent;
public class ExitNotifier extends AbstractComponent {
protected String message;
public ExitNotifier() {
}
@Override
protected ExitNotifierState getState() {
return (ExitNotifierState) super.getState();
}
public ExitNotifier(String message) {
setMessage(message);
}
public String getMessage() {
return getState().getMessage();
}
/**
* The message to display on the confirmation dialog box when the user tries
* to leave the current page. If null or empty, no confirmation dialog will
* be displayed.
*
* @param message
*/
public void setMessage(String message) {
getState().setMessage(message);
}
}
Connector:
package com.infosystem.widgets.vaadin.client.exitNotifier;
import com.google.gwt.core.client.GWT;
import com.google.gwt.user.client.ui.Widget;
import com.infosystem.widgets.vaadin.ExitNotifier;
import com.vaadin.client.communication.StateChangeEvent;
import com.vaadin.client.ui.AbstractComponentConnector;
import com.vaadin.shared.ui.Connect;
@SuppressWarnings("serial")
@Connect(ExitNotifier.class)
public class ExitNotifierConnector extends AbstractComponentConnector {
public ExitNotifierConnector() {
}
@Override
protected Widget createWidget() {
final ExitNotifierWidget widget = GWT.create(ExitNotifierWidget.class);
return widget;
}
@Override
public void onStateChanged(final StateChangeEvent stateChangeEvent) {
super.onStateChanged(stateChangeEvent);
final ExitNotifierState state = getState();
onStateChanged(state);
}
public void onStateChanged(final ExitNotifierState state) {
final ExitNotifierWidget widget = getWidget();
widget.setMessage(state.getMessage());
}
@Override
public ExitNotifierState getState() {
return (ExitNotifierState) super.getState();
}
@Override
public ExitNotifierWidget getWidget() {
return (ExitNotifierWidget) super.getWidget();
}
}
Widget
package com.infosystem.widgets.vaadin.client.exitNotifier;
import com.google.gwt.dom.client.Style;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.SimplePanel;
public class ExitNotifierWidget extends SimplePanel {
private HandlerRegistration handlerRegistration;
public ExitNotifierWidget() {
getElement().getStyle().setDisplay(Style.Display.NONE);
}
public void setMessage(final String message) {
if (handlerRegistration != null) {
handlerRegistration.removeHandler();
}
if (message != null) {
this.handlerRegistration = Window.addWindowClosingHandler(new Window.ClosingHandler() {
@Override
public void onWindowClosing(Window.ClosingEvent event) {
event.setMessage(message);
}
});
}
}
}
State
package com.infosystem.widgets.vaadin.client.exitNotifier;
import com.vaadin.shared.AbstractComponentState;
public class ExitNotifierState extends AbstractComponentState {
private String message;
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
The only issue I have is that Firefox does not show the message, but just a general notice that there might be unsaved data, but I think it is something that is a choice of Firefox creators
This is an old thread, but since it answered partially to my question, I want to put an update here:
public void onWindowClosing(Window.ClosingEvent event) {
event.setMessage(message);
}
This only partially works now. The reason is browsers now does not allow customized message anymore (otherwise a rogue website can fool user with a customized message). A dialog still show up to allow user stay or leave, but the message will be a standard one.