Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular Material: How to position MatDialog relative to element?

I am developping an angular application. I want to open a dialog pop up (an instance of MatDialog) when I click on a button. I do it in a method of my main page as the following

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

I want it to be positioned on the right and underneath the button that I click. At the beginning, I put top: 0px so the pop up displayed on the right up corner of the window. It did it well. After two days I tried to position it just below the button (top: 52px), but it does not work, just as if it keep the previous position (during the first two days). Can you help me

like image 929
flamant Avatar asked Jan 26 '23 15:01

flamant


1 Answers

The MatDialog popup may be positioned relative to an element. In the example below, the dialog is opened below and to the left of the clicked button based on the button's bounding client rectangle. The element may be referenced via a template reference variable.

Then use MatDialogRef method updatePosition.

Main Component Template

<button #myButton></button>

Main Component

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

like image 195
Christopher Peisert Avatar answered Jan 28 '23 10:01

Christopher Peisert