-
Notifications
You must be signed in to change notification settings - Fork 6.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(dialog): expose close attempts #3460
Conversation
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.
In general, I'm not sure whether we should consider successful closes as "attempts". We could emit something along the lines of { type: "backdrop", success: true }
which may come in handy.
src/lib/dialog/dialog-container.ts
Outdated
import 'rxjs/add/operator/first'; | ||
|
||
|
||
/** Possible states for the dialog container animation. */ | ||
export type MdDialogContainerAnimationState = 'void' | 'enter' | 'exit' | 'exit-start'; | ||
|
||
/** Possible types of close events */ | ||
export type MdDialogCloseAttemptsTypes = 'escape' | 'backdrop'; |
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.
Would be better if this were called something like MdDialogCloseAttempt
.
src/lib/dialog/dialog-ref.ts
Outdated
import { | ||
MdDialogContainer, | ||
MdDialogContainerAnimationState, | ||
MdDialogCloseAttemptsTypes |
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.
Add a trailing comma here.
@crisbeto not sure about this, truly successful close is only after animation is done, and this needs to emit at the beginning of the animation. And honestly the only factor that would affect the Other than that I'm all for better naming, but attempt felt fitting. |
Whenever I read "attemp", I assume that it didn't go through, but these obviously can. Perhaps @jelbourn can weigh in? |
@jelbourn can you please please comment, I don't want this to be stuck on just naming for weeks. It would help a ton if it would be merged. |
@crisbeto I consulted with couple of native speakers, they said attempt is alright, that it doesn't at all imply failure |
@crisbeto any news on this PR? Would be great to have it in the next release :) |
I think @jelbourn should weight in on this. |
Another week has gone by.. |
@fxck until then, I think you can rebase this PR, there is some conflicts now :) |
@crisbeto , @jelbourn: I commented on #3251 already, but wanted to raise this ticket up also, as the lack of this hook is causing me some minor annoyance. I would like to allow users to close the dialog however they want, but I need to know when it's about to close in order to prevent bad input. Consider a text input field - the onBlur event is commensurate with the onFocus event that will dismiss the dialog if the click is outside the boundary of my Dialog Component. There is nothing I can do to conditionally prevent the close. If it's the syntax of @crisbeto, To respond to your comment
I'm not certain of course, but I think you're looking at this from the same point of view as I prefer - I would prefer to get a All that said, a If it's just not going to happen, please let us know. Many thanks. |
Any chance of review, now that you are back from ng-conf @jelbourn ? |
@fxck Will this help with the use case of being able to prevent the dialog from closing on an escape or when using the Maybe this is different but if so do you know how to accomplish the use case I am saying? |
@alexw10 Yes, this is exactly what this will allow you to do. |
@frankspin89 I'm also waiting this PR to be merged for that use case .... 👍 |
Took a look at how this works now and the proposed changes. I find the addition of Is there any reason that exposing the overlay's The only other thing in the library that closes a dialog is the |
You can certainly catch escape key by yourself, but you can't quite expect everyone who'd utilise this to know how to do it properly and you could get it easily here for "free", not to mention I think it kinda makes sense. But honestly I'll do anything you tell me to do to get this merged. |
@fxck I think it's important to include caching escape key. Would prevent lot's of new questions related to this topic. But if it's a no go for the material team, please provided detailed documentation to implement caching escape key triggers by yourself. |
@fxck so would changing the PR (or opening a new one) that just exposes the |
Yeah, but it will be pain in the ass to have to set up my own escape key handler with all the logic about whether there are open dialogs etc. It will generate unnecessary issues, I really don't like it, but better than nothing I guess. |
25 days since the last comment and I badly need this once again. Any news ? |
@jelbourn, up to now I've been indifferent about the approach taken by this PR, but with menus getting a I recognize that it's possible and not too difficult for developers to handle the escape handler themselves, but I think whatever approach is chosen here must have a matching API across components. And as the behavior for closing overlays is being defined/refined at a decent clip (#4666, #4843), the value for developers to get this and future refinements for free is huge when compared against the real, but small, cost in complexity. This value is only increased when different components have unique closing requirements (e.g. datepicker selections, menu tabbing out). Further, as shown in this use-case and in #2612, a user may want to disable closing via one method (menu panel click) while retaining other methods (escape key and backdrop click). This would be amazingly easy by just filtering (I realize none of my points are really about dialogs, but I feel strongly about consistent behavior across other overlay-based components) |
want to take this over @willshowell ? |
@fxck I'd be happy to, though since my last comment, the @jelbourn Autocomplete has /**
* A stream of actions that should close the autocomplete panel, including
* when an option is selected, on blur, and when TAB is pressed.
*/
get panelClosingActions(): Observable<MdOptionSelectionChange> {
return merge(
this.optionSelections,
this.autocomplete._keyManager.tabOut,
this._outsideClickStream
);
} which turns out to be very helpful for #3334 (comment), and is not entirely different from the use cases expressed in this thread. What if this PR were organized differently? // dialog.ts
closeAll(): void {
let i = this._openDialogs.length;
while (i--) {
this._openDialogs[i].emitCloseEvent(true);
}
}
private _attachDialogContent<T>(...): MdDialogRef<T> {
// ...
if (config.hasBackdrop) {
overlayRef.backdropClick().subscribe(() => {
dialogRef.emitCloseEvent();
});
}
// ...
}
private _handleKeydown(event: KeyboardEvent): void {
let topDialog = this._openDialogs[this._openDialogs.length - 1];
if (event.keyCode === ESCAPE) {
topDialog.emitCloseEvent();
}
} // dialog-ref.ts
_closeEvent = new Subject<boolean>();
get dialogClosingActions() {
return this._closeEvent.asObservable();
}
emitCloseEvent(forceClose = false) {
this._closeEvent.next(forceClose);
}
ngOnInit() {
this.dialogClosingActions
.filter(forceClose => !this.disableClose || forceClose)
.subscribe(() => this.close());
} (Also, maybe instead of |
My main issue is that I want to avoid any kind of cancellation APIs throughout the library (APIs like
For dialogs specifically, I can see how something like |
@jelbourn Understood. What if each I see that adding the listener to the document solved #3009, and I don't fully understand the caveats, but maybe there is an even better solution that could ultimately provide |
I think anything Is there currently an issue w/ escape closing the dialog if your focus is on a menu/autocomplete/etc.? |
@jelbourn yes, tracking #6223.
Admittedly, replicating an escape listener is easy Observable.fromEvent(document, 'keydown')
.filter(e => e.code === 'Escape')
.takeUntil(this._onDestroy)
.subscribe(() => this.doSomething()); But when you have multiple dialogs, something like this will affect all open dialogs, not just the topmost one. In order to address the original purpose of this PR, I think one of the following must happen:
- if (event.keyCode === ESCAPE && canClose) {
- topDialog.close();
- }
+ if (event.keyCode === ESCAPE) {
+ topDialog.dialogEscape.next(event);
+ }
EDIT: or 3 which could be a full blown EscapeHandler cdk utility 😄 EDIT 2: I'm wondering if backdrop and escape behavior could actually be more coupled since esc seems to be a natural response when something is blocking your interaction with the page. Is refactoring backdrop into its own overlay something you're considering or that just a pipe dream? |
At this point I wouldn't bother with the backdrop since it would be too much of a breaking change. Would it be simplest to just expose the DOM element on |
I don't think that would help though. If the dialog has no focusable elements, or the user has clicked away from the focusable elements in the dialog, keydown events target the last focused item or the body, respectively, instead of the dialog. So they can't be caught by a DOM element ref... unless I'm missing something? See #3009 and https://plnkr.co/edit/puYeeRCta8A7moZOPRWI?p=preview |
Ah, the escape handling changed while I was on vacation back in February. In my head the event listener was still on the dialog container. It feels like there needs to be a more involved keyboard event dispatcher for overlays. Probably one listener on the body that dispatches the event to the appropriate overlay based on some combination of event origin and open order (maybe with a separate priority mechanism). I don't think special-casing escape specifically is a good idea since we could just get into the same situation with another key. |
Cool! So to summarize:
@fxck thoughts? |
Sounds good. |
This issue has been automatically locked due to inactivity. Read more about our automatic conversation locking policy. This action has been performed automatically by a bot. |
Should close #3251
Discussion why is it needed #2853 (comment)
I went with just
backdrop
andescape
attempt types, there could beapi
as well, but I don't really see a use case for that (the reason for this wholecloseAttempts
thing is to be able to catch events you can't really affect, which you definitely can with.close()
.. also I'd require more refactoring).@crisbeto can you review, pretty please.
also cc @jelbourn