Aborting closing of window

Hi,

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.

Hi!

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.

Hi!

This method works but

mainwindow.removeWindow(mywindow);

does not handle

hi jansson,

i implement your piece of code but the browser closes .CAn you help me with this .Its quite Urgent.

Check that you are calling close() on the subwindow and not the main window.

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 .

In short - this is not trivial. See
this thread

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.