Two Mat-Menus on one page, control position for both separately

846 views Asked by At

I have these two menus below. I want to control the cdk-overlay-connected-position-bounding-box css property of both mat menus (their overlays) and align one menu align-items: flex-start; and the other align-items: flex-end;

I have tried setting the align-item property in my local scss file.

.cdk-overlay-connected-position-bounding-box {
   align-items: start !important;
}

but this over rides the align-item property for both menus since the cdk-overlay is a shared class. I have also tried to use two separate components, but the !important over rides css after compiling and both menus have align-item start or end.

How can I isolate position for both menus separately? Please take a look at the stackblitz link

.container {
  display: flex;
  justify-content: space-between;
}
<div class="container">
  <div>
    <button mat-button [matMenuTriggerFor]="menu">Menu One</button>
    <!-- #enddocregion mat-menu-trigger-for -->
    <mat-menu #menu="matMenu">
      <button mat-menu-item>Item 1</button>
      <button mat-menu-item>Item 2</button>
    </mat-menu>
  </div>
  <div>
    <button mat-button [matMenuTriggerFor]="menuTwo">Menu Two</button>
    <!-- #enddocregion mat-menu-trigger-for -->
    <mat-menu #menuTwo="matMenu">
      <button mat-menu-item>Item 1</button>
      <button mat-menu-item>Item 2</button>
    </mat-menu>
  </div>
</div>

https://stackblitz.com/edit/angular-vgmphw?file=src/styles.scss

2

There are 2 answers

5
Riscie On

This works but it makes you dependant on the implementation details of mat-menu, which is not ideal:

Add a backdropClass-input to both menus

<div class="container">
<div>
    <!-- ... -->
    <mat-menu #menu="matMenu" [backdropClass]="'first'">
    <!-- ... -->
</div>
<div>
    <!-- ... -->
    <mat-menu #menuTwo="matMenu" [backdropClass]="'second'">
    <!-- ... -->
</div>
</div>

Target the correct menu with the adjacent sibling combinator (+)

.first+.cdk-overlay-connected-position-bounding-box {
    align-items: start !important;
    background-color: blue !important;
}

.second+.cdk-overlay-connected-position-bounding-box {
    align-items: end !important;
    background-color: green !important;
}

Stackblitz: https://stackblitz.com/edit/angular-vgmphw-bqqjau

5
Eliseo On

I feel you can create two class in styles.scss

.left button.mat-menu-item{
  text-align:left
}
.right button.mat-menu-item{
  text-align:right
}

Then give class to the "mat-menu"

<mat-menu #menu="matMenu" class="left">
  <button mat-menu-item>Item 1</button>
  <button mat-menu-item>Item 2</button>
</mat-menu>

<!--add xPosition before-->
<mat-menu #menu="matMenu" class="right" xPosition="before">
  <button mat-menu-item>Item 1</button>
  <button mat-menu-item>Item 2</button>
</mat-menu>

stackblitz