Angular dialogs should limit promise rejections to error conditions

Bug #1823041 reported by Bill Erickson on 2019-04-03
This bug affects 1 person
Affects Status Importance Assigned to Milestone

Bug Description

Evergreen 3.3

Currently Angular modal dialogs result in a promise rejection when the dialog is dismissed, a Cancel button is clicked, etc. Since these are expected outcomes of modal dialogs and are not error conditions, I propose they be propagated via the dialog promise resolver instead of being rejected. Rejections should be limited to error conditions (e.g. a failed database update performed by the dialog).

A side benefit of this approach is dismissed dialogs will no longer produce console errors for unhandled dismissals.

I propose we also add a 'dismissed' class variable to the base dialog class which may be inspected as needed by the caller, in cases where a dismissal should be treated differently than, say, a Cancel button.

As a simple example, a confirm dialog like this:
    confirmed => doStuff(),
    // avoid console errors by "catching" the dismissal via dummy handler.
    cancelOrDismissOrError => {}

would look like this:
    result => { if (result) { doStuff(); } }

In the second example, an Exception is only thrown and errors logged (via the dialog internals) if an error condition occurs.

This will require modifying a number of existing dialogs in the Angular code. Better now than later, though.

Jane Sandberg (sandbej) wrote :

+1 to not treating closing a modal as an error.

While we're looking at the modals, though, I'm curious if they should return a Promise or an Observable instead. I ask because it seems like it could be very nice to handle success, error, and complete conditions (which RxJs provides), rather than just success and error.

See Angular Material's Observable-based modal:

Also the "Handling the result as an observable" section of this blog post:

Bill Erickson (berick) wrote :

This turned out to be considerably less disruptive than expected.

Code pushed:;a=shortlog;h=refs/heads/user/berick/lp1823041-dialog-dismiss-resolve

From the commit:

Angular dialogs now only result in a promise rejection when an unexpected error occurs. Dismissing a dialog via Esc, Cancel button, cross-click, body-click, etc. no longer result in a rejection. In these situations, the response value will be set to 'null' and a new boolean field 'dismissed' on the dialog object will be set to true.

For the current code, this primarily affects confirm dialogs, which previously rejected the dialog promise when the user selected the "do not confirm" option. Now the confirmation state of the dialog can be inspected by the its boolean response value.

Additionally, this commit adds typescript support for "es2018.promise" which allows us to start using Promise.finally() handlers.


I don't consider this bug especially high priority, but it will impact working branches in progress, so the sooner we merge this one, the less translation work will be needed over time.

Changed in evergreen:
milestone: none → 3.3.1
assignee: Bill Erickson (berick) → nobody
Bill Erickson (berick) wrote :

Interesting, Jane, it had not occurred to me a dialog would produce multiple results, but I can see how that might be useful in some cases. I suppose as a bonus, it's also easy to turn Observables into promises where preferred.

Thinking this through a bit, an Observable dialog would "complete" at dialog close time, it would "error" on exception, and it would produce zero or more "success" events depending on the purpose of the dialog.

A confirm dialog, for example, may produce a "success" on confirm, but nothing on un-comfirm. In either case, the user can easily tell when the dialog is closed via its complete handler...

I think the code I just pushed moves us a little closer in this direction, so it could be built upon...

+1 from me

Bill Erickson (berick) wrote :

Addendum to my previous comment, a confirm dialog should still produce a success event with a true/false result, in part because they are both expected results, but also so the caller is not required to implement a complete handler to know the dialog is done.

Changed in evergreen:
assignee: nobody → Bill Erickson (berick)
status: New → In Progress
Bill Erickson (berick) wrote :
Changed in evergreen:
assignee: Bill Erickson (berick) → nobody
status: In Progress → Confirmed
tags: added: pullrequest
Changed in evergreen:
milestone: 3.3.1 → 3.3.2
Jane Sandberg (sandbej) on 2019-06-19
Changed in evergreen:
assignee: nobody → Jane Sandberg (sandbej)
importance: Undecided → Medium
Jane Sandberg (sandbej) wrote :

Here's a branch that signs off on Bill's commit, rebases against master, and welcomes some new dialogs into the world of Observables. :-D


Changed in evergreen:
assignee: Jane Sandberg (sandbej) → nobody
Bill Erickson (berick) wrote :

Thanks, Jane.

Follow-up branch pushed including sign-off to your commit and a few more commits to repair some lingering dialog issues and clean some stuff up.;a=shortlog;h=refs/heads/user/berick/lp1823041-angular-dialog-observable-part2

Jane Sandberg (sandbej) wrote :

Works well for me, Bill. Thanks very much.

Signoff branch here: user/sandbergja/lp1823041-angular-dialog-observable-part2-signoff

tags: added: signedoff
Bill Erickson (berick) on 2019-06-20
Changed in evergreen:
assignee: nobody → Bill Erickson (berick)
Bill Erickson (berick) wrote :

Thanks, Jane! Merged to 3.3 and master.

Changed in evergreen:
status: Confirmed → Fix Committed
assignee: Bill Erickson (berick) → nobody
Changed in evergreen:
status: Fix Committed → Fix Released
To post a comment you must log in.
This report contains Public information  Edit
Everyone can see this information.

Other bug subscribers