feat(panel): Adding a hook on close success. #9819
Conversation
@ErinCoughlan @DerekLouie wouldn't this be more appropriate to pass to the |
@crisbeto Interceptors intercept the close events, so they are run before close is finished and can block the close from happening. The goal of this PR is to allow the user to run events after the panel is closed, similar to the animation hooks for This already works for explicit close events because the user can chain off of the close call. But on pressing escape or clicking on the backdrop, we don't give the user any way to know these events happened or allow them to do work after it's closed. The most common use case of this is a dialog where when the panel is closed you need to reject/resolve the promise from open. This currently is not possible. |
Alright, that makes sense. Regarding the promise: didn't we have a task somewhere to have it be a part of the |
@@ -126,6 +126,9 @@ angular | |||
* outside the panel to close it. Defaults to false. | |||
* - `escapeToClose` - `{boolean=}`: Whether the user can press escape to | |||
* close the panel. Defaults to false. | |||
* - `postClose` - `{function=}`: Function that is called after close |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think naming this onCloseSuccess
would be more appropriate.
@@ -1153,20 +1156,24 @@ MdPanelRef.prototype.open = function() { | |||
|
|||
/** | |||
* Closes the panel. | |||
* @param {string} closeEvent The event type that triggered the close. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This parameter would most likely not be a string. Events are normally MouseEvent
, or AngularEvent
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You should probably not mention "event" here, since that means something very different to most people, as @bradrich mentioned. Perhaps, closeReason, closeCause, or even just "reason" or "cause" would work.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ErinCoughlan Good catch! I was thinking that it was going to be the event that the occurred to get there, not a string representation.
@@ -1043,6 +1043,7 @@ describe('$mdPanel', function() { | |||
clickPanelContainer(); | |||
|
|||
expect(myButton).toBeFocused(); | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why the extra lines here?
}); | ||
}); | ||
}); | ||
|
||
describe('postClose logic:', function() { | ||
it('postClose when provided', function () { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These tests should have more descriptive names. See the rest of the it
tests, they all have the form of should do something when something...
. These tests are failing in Travis and it wasn't immediately apparent without reading the tests what the test was trying to accomplish.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Follow the same test naming as the other events we fire, like onOpenComplete
or onRemoving
.
@@ -126,6 +126,9 @@ angular | |||
* outside the panel to close it. Defaults to false. | |||
* - `escapeToClose` - `{boolean=}`: Whether the user can press escape to | |||
* close the panel. Defaults to false. | |||
* - `postClose` - `{function=}`: Function that is called after close | |||
* is done. The first parameter passed into this function is the closeEvent | |||
* and the 2nd is the current panelRef. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought panelRef
was first because that has to be defined and closeEvent
is optional.
You should also mention the two events for pressEscapeToClose
and clickBackdropToClose
or no one will know how to use them.
@@ -126,6 +126,9 @@ angular | |||
* outside the panel to close it. Defaults to false. | |||
* - `escapeToClose` - `{boolean=}`: Whether the user can press escape to | |||
* close the panel. Defaults to false. | |||
* - `postClose` - `{function=}`: Function that is called after close |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
{function(panelRef, string)=} is the correct type, especially since this has params.
@@ -126,6 +126,9 @@ angular | |||
* outside the panel to close it. Defaults to false. | |||
* - `escapeToClose` - `{boolean=}`: Whether the user can press escape to | |||
* close the panel. Defaults to false. | |||
* - `postClose` - `{function=}`: Function that is called after close | |||
* is done. The first parameter passed into this function is the closeEvent |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Possible re-word to "after close has successfully finished". "done" is too vague for this, since it will not be called if the panel fails the close.
@@ -1153,20 +1156,24 @@ MdPanelRef.prototype.open = function() { | |||
|
|||
/** | |||
* Closes the panel. | |||
* @param {string} closeEvent The event type that triggered the close. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You should probably not mention "event" here, since that means something very different to most people, as @bradrich mentioned. Perhaps, closeReason, closeCause, or even just "reason" or "cause" would work.
@@ -1704,7 +1711,7 @@ MdPanelRef.prototype._configureEscapeToClose = function() { | |||
ev.stopPropagation(); | |||
ev.preventDefault(); | |||
|
|||
self.close(); | |||
self.close("escapeToClose"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There should be an enum that the user can access for the different close causes (like the enum for positioning or animations).
String values are dangerous because it allows for typos.
}); | ||
}); | ||
}); | ||
|
||
describe('postClose logic:', function() { | ||
it('postClose when provided', function () { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Follow the same test naming as the other events we fire, like onOpenComplete
or onRemoving
.
describe('postClose logic:', function() { | ||
it('postClose when provided', function () { | ||
var obj = { | ||
postClose: function() {}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do you need to make an object here? Does it suffice to just create a spy, then pass it to the config?
var onCloseSuccess = jasmine.createSpy('onCloseSuccess');
var config = angular.extend({ 'postClose': onCloseSuccess });
openPanel(config);
closePanel();
expect(onCloseSuccess).toHaveBeenCalledWith(panelRef, undefined);
e204658
to
85fa302
Compare
Hello! All the aforementioned comments have been addressed, please take another look at this PR at your earliest convenience :) |
LGTM |
@@ -126,6 +126,12 @@ angular | |||
* outside the panel to close it. Defaults to false. | |||
* - `escapeToClose` - `{boolean=}`: Whether the user can press escape to | |||
* close the panel. Defaults to false. | |||
* - `onCloseSuccess` - `{function(panelRef, string)=}`: Function that is |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
!panelRef
* - `onCloseSuccess` - `{function(panelRef, string)=}`: Function that is | ||
* called after the close successfully finishes. The first parameter passed | ||
* into this function is the current panelRef and the 2nd is an optional | ||
* string explaining the close reason. Currently 'pressEscapeToClose' and |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Aren't these enums? that the user can get access to?
* Possible default closeReasons for the close function. | ||
* @enum {string} | ||
*/ | ||
MdPanelRef.closeReasons = { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You'll want this to be exported on the mdPanel service as well so users can access them. (Follow what the other enums did.)
@@ -1059,6 +1059,77 @@ describe('$mdPanel', function() { | |||
}); | |||
}); | |||
|
|||
describe('onCloseSuccess logic:', function() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think these tests should be it's own group. This functionality is part of the close logic, and therefore should be individual tests after the other close callback tests.
Like this:
https://github.com/angular/material/blob/master/src/components/panel/panel.spec.js#L877
clickPanelContainer(); | ||
|
||
expect(onCloseSuccessCalled).toBe(true); | ||
expect(closeReason).toBe('clickOutsideToClose'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use the enums in the tests too, not strings.
d6dc99a
to
40e534c
Compare
Fixed the enums / documentation comments. Please take another look at your earliest convenience :). |
40e534c
to
132c106
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
132c106
to
5e6eeb5
Compare
Hello,
@ErinCoughlan @bradrich
Here is a small PR to add an "on close success" hook for users who want to run some code after a panel successfully closes.
It also adds an optional parameter to the "close" function which allows the user to specify a string describing why the close happened (standardized strings have been added to the "escapeToClose" and "clickOutsideToClose" functions.
Please Review.