0

I am trying to get the screen dimensions of a just opened Angular Material dialog box. What is the best way to do that?

Background: I am using Angular Material 5.2.5 and am unable to upgrade. If a dialog box is too tall for the window, it gets clipped at the top and the bottom and there is no way to reach the action buttons at the bottom. See Dialog position and size problems on GitHub.

When the dialog opens, I would like to check its position to see if any part of it is off screen. If so, I will apply a class to make the dialog full-screen and adjust the scrollable parts so the users can get to everything. (Other ideas welcome.)

What I've Tried:

1. I tried using a template variable on a wrapper element:

<button mat-raised-button (click)="showDialog()">Click me to show dialog</button>

<ng-template #dialogTemplate>
  <div #dialogFrame class="dialog-frame">
    <div> ... dialog content ... </div>
  </div>
</ng-template>

Then in the component's showDialog() function:

...
export class dialogButtonComponent implements OnInit {
  @ViewChild('dialogTemplate') private dialogModal: TemplateRef<any>;
  @ViewChild('dialogFrame', {read: ElementRef}) private dialogFrame: ElementRef;
  ...
  showDialog(config: MatDialogConfig = {}) {
    this.dialogRef = this.dialog.open(this.dialogModal, dialogConfig);
    const box = this.dialogFrame.nativeElement.getBoundingClientRect();
      // this.dialogFrame is undefined when this executes
  }
}

2. Based on this answer, I tried injecting MatDialogContainer to get a reference:

We also need to inject MatDialogContainer in our directive so that we can get initial position of dialog container. We have to calculate initial offset because Angular material library uses flex to center dialog and it doesn't get us specific top/left values.

Specifically:

const box = this.container['_elementRef'].nativeElement.getBoundingClientRect();

Where this.container is the injected MatDialogContainer. I tried doing this in my component, but had trouble injecting it. I haven't worked with directives as much, so I'm looking into that.

3. On the dialogRef returned from opening the dialog box, access dialogRef._containerInstance._elementRef:

...
const dialogRef = this.dialog.open(this.overlayModal, dialogConfig);
const dialogBoxElement = dialogRef._containerInstance._elementRef;

// dialogBoxElement now has an ElementRef that I can call getBoundingClientRect() on.

This actually works locally, but it won't build. The problem is that there's a Typescript error because "Property '_elementRef' is private and only accessible within class 'MatDialogContainer'."


I hope there is a simpler way to get the screen coordinates of an Angular Material dialog box. Any ideas?

Scott McD.
  • 99
  • 1
  • 11
  • In your dialog component put private var for elementRef in CTOR. Then put in properties for width and height or emit their values. The nativeElment property you want is actualwidth and actualheight. – JWP Apr 07 '20 at 23:26
  • @JohnPeters - Thanks! When I inject elementRef in the constructor function, the information I get is for the button you click to bring up the dialog box. (See number 1 above.) The box itself is in the template and given a template variable - it's not a separate component. It gets appended to the DOM and isn't a child of the button, so I can't drill down to find it. I suppose I could pull the template out and have the contents of the box be an actual separate component, but that would introduce other problems as well. – Scott McD. Apr 08 '20 at 21:04
  • Can you post simple solution to [stackblitz](https://stackblitz.com/edit/angular-te1ua4) so we can see the problem? – JWP Apr 08 '20 at 21:54

0 Answers0