Angular Material: 如何相对于元素定位MatDialog?

Angular Material: How to position MatDialog relative to element?

我正在开发 angular 应用程序。当我点击一个按钮时,我想打开一个弹出对话框(MatDialog 的一个实例)。我在我的主页的方法中做如下

    openDialog(event) {
      const element = document.getElementById(event.target.id);
      const jqelement = $(element);
      const position = jqelement.position(); // cache the position
      const bottom = position.top + jqelement.height();
      const dialogConfig = new MatDialogConfig();
      dialogConfig.disableClose = true;
      dialogConfig.autoFocus = true;
      dialogConfig.position = {
        top:  '' + bottom,
        right: '0'
      };
      dialogConfig.width = '50%' ;
      dialogConfig.height = '350px' ;
      console.log(dialogConfig);
      this.dialog.open(UserDialogComponent, dialogConfig);
    }

我希望它位于我单击的按钮的右侧和下方。一开始,我把 top: 0px 放在 window 的右上角弹出。它做得很好。两天后,我试图将它定位在按钮下方(顶部:52px),但它不起作用,就像它保持以前的位置一样(在前两天)。你能帮帮我吗

MatDialog 弹出窗口可以相对于元素定位。在下面的示例中,对话框根据按钮的边界客户端矩形在单击按钮的下方和左侧打开。可以通过模板引用变量引用该元素。

然后使用MatDialogRef方法updatePosition.

主要组件模板

<button #myButton></button>

主要成分

import { AfterViewInit, Component, ElementRef, OnDestroy, ViewChild } from '@angular/core'
import { DialogService } from './dialog.service.ts'

@Component({
  selector: 'main-component',
  templateUrl: 'main.component.html',
  styleUrls: ['main.component.css']
})
export class MainComponent implements AfterViewInit, OnDestroy {
  @ViewChild('myButton', { static: false }) public myButtonRef: ElementRef

  constructor(private dialogService: DialogService) {}

  public openDialog() {
    dialogRef = this.dialogService.openDialog({
      positionRelativeToElement: this.myButtonRef,
      has_backdrop: true
    })

    this.dialogRef.afterClosed().subscribe(
      () => {
        ...
        this.dialogRef = null
      }
    )
  }
}

dialog.component.ts

import { Component, ElementRef, Inject, OnInit } from '@angular/core'
import { MatDialogConfig, MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog'


@Component({
  selector: 'dialog-component',
  templateUrl: './dialog.component.html',
  styleUrls: ['./dialog.component.css']
})
export class DialogComponent implements OnInit {
  private positionRelativeToElement: ElementRef

  constructor(public dialogRef: MatDialogRef<DialogComponent>,
    @Inject(MAT_DIALOG_DATA) public options: { positionRelativeToElement: ElementRef }) {

    this.positionRelativeToElement = options.positionRelativeToElement
  }

  ngOnInit() {
    const matDialogConfig = new MatDialogConfig()
    const rect: DOMRect = this.positionRelativeToElement.nativeElement.getBoundingClientRect()

    matDialogConfig.position = { right: `10px`, top: `${rect.bottom + 2}px` }
    this.dialogRef.updatePosition(matDialogConfig.position)
  }
}

dialog.service.ts

import { ElementRef, Injectable } from '@angular/core'
import { MatDialog, MatDialogRef } from '@angular/material'

import { DialogComponent } from './dialog.component'


/**
 * Service to create modal dialog windows.
 */
@Injectable({
  providedIn: 'root'
})
export class DialogService {

  constructor(public dialog: MatDialog) { }

  public openDialog({ position_relative_to_element, user,
    has_backdrop = false, height = '135px', width = '290px' }:
    {
      positionRelativeToElement: ElementRef, hasBackdrop?: boolean,
      height?: string, width?: string
    }): MatDialogRef<DialogComponent> {

    const dialogRef: MatDialogRef<DialogComponent> =
      this.dialog.open(DialogComponent, {
        hasBackdrop: hasBackdrop,
        height: height,
        width: width,
        data: { positionRelativeToElement: positionRelativeToElement }
      })
    return dialogRef
  }
}