Skip to content

Commit

Permalink
refactor(cdk/dialog): Consolidate afterNextRender calls (#29237)
Browse files Browse the repository at this point in the history
(cherry picked from commit 70780a6)
  • Loading branch information
mmalerba committed Jun 12, 2024
1 parent b903ee3 commit 08f34bc
Showing 1 changed file with 25 additions and 43 deletions.
68 changes: 25 additions & 43 deletions src/cdk/dialog/dialog-container.ts
Original file line number Diff line number Diff line change
Expand Up @@ -257,61 +257,43 @@ export class CdkDialogContainer<C extends DialogConfig = DialogConfig>
return;
}

const element = this._elementRef.nativeElement;
// If were to attempt to focus immediately, then the content of the dialog would not yet be
// ready in instances where change detection has to run first. To deal with this, we simply
// wait for the microtask queue to be empty when setting focus when autoFocus isn't set to
// dialog. If the element inside the dialog can't be focused, then the container is focused
// so the user can't tab into other elements behind it.
const autoFocus = this._config.autoFocus;
switch (autoFocus) {
case false:
case 'dialog':
// Ensure that focus is on the dialog container. It's possible that a different
// component tried to move focus while the open animation was running. See:
// https://github.com/angular/components/issues/16215. Note that we only want to do this
// if the focus isn't inside the dialog already, because it's possible that the consumer
// turned off `autoFocus` in order to move focus themselves.
afterNextRender(
() => {
// wait until after the next render.
afterNextRender(
() => {
const element = this._elementRef.nativeElement;
switch (this._config.autoFocus) {
case false:
case 'dialog':
// Ensure that focus is on the dialog container. It's possible that a different
// component tried to move focus while the open animation was running. See:
// https://github.com/angular/components/issues/16215. Note that we only want to do this
// if the focus isn't inside the dialog already, because it's possible that the consumer
// turned off `autoFocus` in order to move focus themselves.
if (!this._containsFocus()) {
element.focus();
}
},
{injector: this._injector},
);
break;
case true:
case 'first-tabbable':
afterNextRender(
() => {
break;
case true:
case 'first-tabbable':
const focusedSuccessfully = this._focusTrap?.focusInitialElement();
// If we weren't able to find a focusable element in the dialog, then focus the dialog
// container instead.
if (!focusedSuccessfully) {
this._focusDialogContainer();
}
},
{injector: this._injector},
);
break;
case 'first-heading':
afterNextRender(
() => {
break;
case 'first-heading':
this._focusByCssSelector('h1, h2, h3, h4, h5, h6, [role="heading"]');
},
{injector: this._injector},
);
break;
default:
afterNextRender(
() => {
this._focusByCssSelector(autoFocus!);
},
{injector: this._injector},
);
break;
}
break;
default:
this._focusByCssSelector(this._config.autoFocus!);
break;
}
},
{injector: this._injector},
);
}

/** Restores focus to the element that was focused before the dialog opened. */
Expand Down

0 comments on commit 08f34bc

Please sign in to comment.