Skip to content

Commit 702f6f6

Browse files
authored
feat: add addClosedListener to Dialog (#7794)
1 parent b0a2332 commit 702f6f6

File tree

2 files changed

+61
-5
lines changed
  • vaadin-dialog-flow-parent/vaadin-dialog-flow/src

2 files changed

+61
-5
lines changed

vaadin-dialog-flow-parent/vaadin-dialog-flow/src/main/java/com/vaadin/flow/component/dialog/Dialog.java

Lines changed: 38 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -286,8 +286,12 @@ public String getTop() {
286286
}
287287

288288
/**
289-
* {@code opened-changed} event is sent when the overlay opened state
290-
* changes.
289+
* Event that is fired when the dialog's opened state changes.
290+
* <p>
291+
* Note that this event fires immediately when the opened property changes,
292+
* which, when closing the dialog, is before the closing animation has
293+
* finished. To wait for the animation to finish, listen for the
294+
* {@link ClosedEvent} event.
291295
*/
292296
public static class OpenedChangeEvent extends ComponentEvent<Dialog> {
293297
private final boolean opened;
@@ -302,6 +306,17 @@ public boolean isOpened() {
302306
}
303307
}
304308

309+
/**
310+
* Event that is fired after the dialog's closing animation has finished.
311+
* Can be used to remove a dialog from the UI afterward.
312+
*/
313+
@DomEvent("closed")
314+
public static class ClosedEvent extends ComponentEvent<Dialog> {
315+
public ClosedEvent(Dialog source, boolean fromClient) {
316+
super(source, fromClient);
317+
}
318+
}
319+
305320
@Override
306321
public void setWidth(String value) {
307322
getElement().setProperty("width", value);
@@ -969,7 +984,12 @@ private void setModality(boolean modal) {
969984
}
970985

971986
/**
972-
* Add a lister for event fired by the {@code opened-changed} events.
987+
* Add a listener for when the dialog's opened state changes.
988+
* <p>
989+
* Note that this event fires immediately when the opened property changes,
990+
* which, when closing the dialog, is before the closing animation has
991+
* finished. To wait for the animation to finish, use
992+
* {@link #addClosedListener(ComponentEventListener)}.
973993
*
974994
* @param listener
975995
* the listener to add
@@ -980,6 +1000,19 @@ public Registration addOpenedChangeListener(
9801000
return addListener(OpenedChangeEvent.class, listener);
9811001
}
9821002

1003+
/**
1004+
* Add a lister for when the dialog's closing animation has finished. Can be
1005+
* used to remove the dialog from the UI afterward.
1006+
*
1007+
* @param listener
1008+
* the listener to add
1009+
* @return a Registration for removing the event listener
1010+
*/
1011+
public Registration addClosedListener(
1012+
ComponentEventListener<ClosedEvent> listener) {
1013+
return addListener(ClosedEvent.class, listener);
1014+
}
1015+
9831016
/**
9841017
* {@inheritDoc}
9851018
* <p>
@@ -996,8 +1029,8 @@ public Registration addAttachListener(
9961029
* {@inheritDoc}
9971030
* <p>
9981031
* Note: To listen for closing the dialog, you should use
999-
* {@link #addOpenedChangeListener(ComponentEventListener)}, as the
1000-
* component is not necessarily removed from the DOM when closing.
1032+
* {@link #addClosedListener(ComponentEventListener)}, as the component is
1033+
* not necessarily removed from the DOM when closing.
10011034
*/
10021035
@Override
10031036
public Registration addDetachListener(

vaadin-dialog-flow-parent/vaadin-dialog-flow/src/test/java/com/vaadin/flow/component/dialog/DialogTest.java

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import org.mockito.Mockito;
2727

2828
import com.vaadin.flow.component.Component;
29+
import com.vaadin.flow.component.ComponentEventListener;
2930
import com.vaadin.flow.component.ComponentUtil;
3031
import com.vaadin.flow.component.HasStyle;
3132
import com.vaadin.flow.component.Key;
@@ -34,8 +35,13 @@
3435
import com.vaadin.flow.component.html.Div;
3536
import com.vaadin.flow.component.html.Span;
3637
import com.vaadin.flow.component.internal.PendingJavaScriptInvocation;
38+
import com.vaadin.flow.dom.DomEvent;
39+
import com.vaadin.flow.dom.Element;
40+
import com.vaadin.flow.internal.nodefeature.ElementListenerMap;
3741
import com.vaadin.flow.server.VaadinSession;
3842

43+
import elemental.json.Json;
44+
3945
/**
4046
* Unit tests for the Dialog.
4147
*/
@@ -420,6 +426,23 @@ public void position_setTopLeft_positionIsDefined() {
420426
Assert.assertEquals("20px", dialog.getLeft());
421427
}
422428

429+
@SuppressWarnings("unchecked")
430+
@Test
431+
public void addClosedListener_listenerInvokedOnClose() {
432+
Dialog dialog = new Dialog();
433+
ComponentEventListener<Dialog.ClosedEvent> listener = Mockito
434+
.mock(ComponentEventListener.class);
435+
dialog.addClosedListener(listener);
436+
437+
Element element = dialog.getElement();
438+
dialog.getElement().getNode().getFeature(ElementListenerMap.class)
439+
.fireEvent(
440+
new DomEvent(element, "closed", Json.createObject()));
441+
442+
Mockito.verify(listener, Mockito.times(1))
443+
.onComponentEvent(Mockito.any(Dialog.ClosedEvent.class));
444+
}
445+
423446
private void fakeClientResponse() {
424447
ui.getInternals().getStateTree().runExecutionsBeforeClientResponse();
425448
ui.getInternals().getStateTree().collectChanges(ignore -> {

0 commit comments

Comments
 (0)