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

fla*_*ant 3 popup angular-material 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);
}
Run Code Online (Sandbox Code Playgroud)

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

Chr*_*ert 5

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

然后使用MatDialogRef方法updatePosition

主要组件模板

<button #myButton></button>
Run Code Online (Sandbox Code Playgroud)

主要组件

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
      }
    )
  }
}
Run Code Online (Sandbox Code Playgroud)

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)
  }
}

Run Code Online (Sandbox Code Playgroud)

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
  }
}

Run Code Online (Sandbox Code Playgroud)