thinktanker
thinktanker

Reputation: 139

How to display mat-select options on top of dialog window?

The solution I found to set in global css file:

.cdk-global-overlay-wrapper, .cdk-overlay-container {
  z-index: 10000;
}

breaks other dialog windows (e.g. the MatDatepicker used inside form in MatDialog displays behind it). Setting it locally seems to have no effect, changing view encapsulation according to this post: Displaying a mat-select inside a modal dialog still breaks other dialog windows (the same as global set style). Can I achieve it any other way?

Edited:

Example stackblitz, where select options don't even display: https://stackblitz.com/edit/angular-jkxsig-en8bze?file=app/

Upvotes: 0

Views: 6053

Answers (2)

thinktanker
thinktanker

Reputation: 139

Ok, seems like I found reason of problem and the solution. So the reason of the problem is the fact that bootstrap modal window (ngb-modal-window) appears under background (ngb-modal-backdrop), as described here:

Bootstrap modal appearing under background

Setting modal window z-index has no effect, because backdrop is always higher in stacking context, and bootstrap framework always overrides its z-index to 1050 after component creation. There are two solutions to the problem, which I found here:

Bootstrap modal appearing under background

1.) Disable backdrop using NgbModalOptions (setting backdrop property to false) and adding class for modal window (setting windowClass property). Then set very low value for z-index for our window class, like this, in global style.css file:

ngb-modal-window.test {
    z-index: 1;
}

The drawback is, we don't have backdrop for our bootstrap modal now.

2.) Adding modal window directly under body container in html hierarchy or just append it to it, like explained here:

https://github.com/twbs/bootstrap/issues/23916

I have not tested it, but it should work, here you can find info how to append element to html body:

https://hackernoon.com/angular-pro-tip-how-to-dynamically-create-components-in-body-ba200cc289e6

Upvotes: 1

indrajeet
indrajeet

Reputation: 897

When i initialize the id it worked.

import {Component} from '@angular/core';

import {NgbModal, ModalDismissReasons} from '@ng-bootstrap/ng-bootstrap';

export interface Food {
  value: string;
  viewValue: string;
}

@Component({
  selector: 'ngbd-modal-basic',
  templateUrl: './modal-basic.html'
})
export class NgbdModalBasic {
    foods: Food[] = [
    {value: 'steak-0', viewValue: 'Steak'},
    {value: 'pizza-1', viewValue: 'Pizza'},
    {value: 'tacos-2', viewValue: 'Tacos'}
  ];
  closeResult: string;
  ariaId = 'modal-basic-title';

  constructor(private modalService: NgbModal) {}

  open(content) {
    this.modalService.open(content, { ariaLabelledBy: 'modal-basic-title', size: 'lg', backdrop: 'static' }, ).result.then((result) => {
      this.closeResult = `Closed with: ${result}`;
    }, (reason) => {
      this.closeResult = `Dismissed ${this.getDismissReason(reason)}`;
    });
  }

  private getDismissReason(reason: any): string {
    if (reason === ModalDismissReasons.ESC) {
      return 'by pressing ESC';
    } else if (reason === ModalDismissReasons.BACKDROP_CLICK) {
      return 'by clicking on a backdrop';
    } else {
      return  `with: ${reason}`;
    }
  }
}

html

<ng-template #content let-modal let-id="ariaId">
  <div class="modal-header">
    <h4 class="modal-title" id="{{ariaId}}">Profile update</h4>
    <button type="button" class="close" aria-label="Close" (click)="modal.dismiss('Cross click')">
      <span aria-hidden="true">&times;</span>
    </button>
  </div>
  <div class="modal-body">
    <form>
      <div class="form-group">
        <label for="dateOfBirth">Date of birth</label>
        <div class="input-group">
          <input id="dateOfBirth" class="form-control" placeholder="yyyy-mm-dd" name="dp" ngbDatepicker #dp="ngbDatepicker">
          <div class="input-group-append">
            <button class="btn btn-outline-secondary calendar" (click)="dp.toggle()" type="button"></button>
          </div>
        </div>
      </div>
      <h4>Basic mat-select</h4>
      <mat-form-field>
        <mat-label>Favorite food</mat-label>
        <mat-select>
          <mat-option *ngFor="let food of foods" [value]="food.value">
            {{food.viewValue}}
          </mat-option>
        </mat-select>
      </mat-form-field>
    </form>
  </div>
  <div class="modal-footer">
    <button type="button" class="btn btn-outline-dark" (click)="modal.close('Save click')">Save</button>
  </div>
</ng-template>

<button class="btn btn-lg btn-outline-primary" (click)="open(content)">Launch demo modal</button>

<hr>

<pre>{{closeResult}}</pre>

Upvotes: 0

Related Questions