Angular material dialog component hides all my web

2020-07-08 07:36发布

问题:

I'm using angular 5 and angular material (latest version) and I'm trying to open a dialog from a page. When I click the button that triggers the opening, the entire website is put in blank background like if the dialog were overlaping it contents and hiding it all.

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

@Component({
    moduleId: module.id,
    selector: 'app-dialog',
    templateUrl: 'dialog.component.html',
    styleUrls: ['dialog.component.scss']
})
export class DialogComponent implements OnInit {

    constructor(public dialogRef: MatDialogRef<DialogComponent>,
        @Inject(MAT_DIALOG_DATA) public data: any) { }

    onNoClick(): void {
        this.dialogRef.close();
    }

    ngOnInit() {
    }

}

And this is the method that opens the Dialog.

onSubmit() {

        const dialogRef = this.dialog.open(DialogComponent, {
            width: '250px',
            data: { name: 'Juan Manuel', animal: 'Perro' }
        });

        dialogRef.afterClosed().subscribe(result => {
            console.log('The dialog was closed');
            console.log(result);
        });
    }

UPDATE: I've seen that after the dialog is rendered a class is added to my html tag. .cdk-global-scrollblock I don't know why is that class added to my html tag.

.cdk-global-scrollblock {
    position: fixed;
    width: 100%;
    overflow-y: scroll;
}

That what's causing my error. Does someone knows why is that class on my html tag?

回答1:

This is due to cdk-global-scrollblock that is injected into the HTML body which will affect your components that have position absolute.

You can override it in the Angular Material theme CSS with:

.cdk-global-scrollblock {
    position: static;
    overflow: hidden !important;
}

or with deprecated Shadow-Piercing:

/deep/ .cdk-global-scrollblock {
    position: static;
    overflow: hidden !important;
}


回答2:

Easiest fix would be setting the dialog scroll strategy to new NoopScrollStrategy object:

const dialogRef = this.dialog.open(DialogComponent, {
        width: '250px',
        data: { name: 'Juan Manuel', animal: 'Perro' },
        scrollStrategy: new NoopScrollStrategy()
    });

this will only require an extra import:

import { NoopScrollStrategy } from '@angular/cdk/overlay';


回答3:

See the API Docs for MatDialogConfig. You can set hasBackdrop to false.

    const dialogRef = this.dialog.open(DialogComponent, {
        width: '250px',
        data: { name: 'Juan Manuel', animal: 'Perro' },
        hasBackdrop: false
    });


回答4:

I faced same problem. Following solution work for me,

.cdk-global-scrollblock{
    position: static !important;
    width: initial !important;
    overflow-y: inherit !important;
  }

Put it into your global css or in dialog components loacl css (you have to enable view encapsulation in case of local)



回答5:

I get with the same problem.İt looked like that in my css runtime.

https://www.resimag.com/p1/ff8da3c59ae.jpeg

enter image description here

For this, my solution was; I import the ViewEncapsulation object in my component.You can learn how it is used and what it does. https://dzone.com/articles/what-is-viewencapsulation-in-angular https://angular.io/api/core/ViewEncapsulation

After In css I wrote this code; "position: initial; width: initial; overflow: hidden;"

"position: initial; width:initial;" turn back the value that it received first.

This is my dialog.component.css;

.cdk-global-scrollblock {
  position: initial;
  width: initial;
  overflow: hidden;
}

This is my dialog.component.ts;

import {Component, OnInit,Inject, ViewEncapsulation} from '@angular/core';
import {  MatDialogRef,  MAT_DIALOG_DATA } from '@angular/material';

@Component({
  selector: 'app-dialog',
  encapsulation: ViewEncapsulation.None,
  templateUrl: 'dialog.component.html',
  styleUrls: ['dialog.component.css']
})
export class DialogComponent implements OnInit {

  constructor(public dialogRef: MatDialogRef < DialogComponent > ,
    @Inject(MAT_DIALOG_DATA) public data: any) {}

  onNoClick(): void {
    this.dialogRef.close();
  }

  ngOnInit() {}

}


回答6:

Just add this override css or scss class to fix the background invisible issue.

.cdk-global-scrollblock{
    position: initial;
}


回答7:

In order to fully understand why .cdk-global-scrollblock is added to the html tag, I want to make a short description of MatDialog Scroll Strategies:

MatDialog Scroll Stragies

MatDialog component has the option scrollStrategy (type ScrollStrategy), which determines the scroll strategy to be used for the dialog, as described in: https://material.angular.io/components/dialog/api#MatDialogConfig

To associate the scroll strategy, you have to pass in a function, that returns a scroll strategy, to the MatDialogConfig:

const dialogRef = this.dialog.open(DialogComponent, {
    scrollStrategy: this.overlay.scrollStrategies.block()
    // .. other options
});

By default, the MatDialogwill use the block strategy, as found in the source code.

The other available strategies are noop, reposition, and close - as described here.


.cdk-global-scrollblock css class

This class is added to the html tag when the block strategy is used. It is used to block the scroll of the content behind the dialog, especially on mobile devices (iOS) - that's why position: fixed; is used. But when this rule is applied, the window will scroll back to the top of the screen. So there is a need to calculate the current the scroll of the window and apply it to the html tag.

Source code can be found here, in BlockScrollStrategy class. I will copy some code here:

this._previousScrollPosition = this._viewportRuler.getViewportScrollPosition();

// Note: we're using the `html` node, instead of the `body`, because the `body` may
// have the user agent margin, whereas the `html` is guaranteed not to have one.
  root.style.left = coerceCssPixelValue(-this._previousScrollPosition.left);
  root.style.top = coerceCssPixelValue(-this._previousScrollPosition.top);
  root.classList.add('cdk-global-scrollblock');

Solutions

1. The real problem is with your css.

For sure that the values for this._previousScrollPosition are not correct, so double check the css rules added to the html and body tags.

I was able to replicate your issue by using the following css:

html, body {
  min-height: 100%;
  height: 100%;
}

body {
 overflow: auto;
}

Example here: https://stackblitz.com/edit/angular-xvucu4.

This can be fixed by removing body { overflow: auto; }.

Example here: https://stackblitz.com/edit/angular-xvucu4-jek3zb.

If you really need html and body to take 100% of the viewport, even is the content is smaller, use the following css:

html {
    height: 100%;
}

body {
   min-height: 100%:
}

OR

2. Set noop scroll strategy:

const dialogRef = this.dialog.open(DialogComponent, {
    scrollStrategy: this.overlay.scrollStrategies.noop() 
    // .. other options
});

The page content will scroll, even if the dialog is opened.

Example: https://stackblitz.com/edit/angular-xvucu4-t4uwwb.