1

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

Generaldeep
  • 437
  • 2
  • 12
  • 30

2 Answers2

2

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

Riscie
  • 3,775
  • 1
  • 24
  • 31
  • This works! I did not know about adjacent sibling combinator, I still don't fully understand how this code is able to control the position of the cdk-overlay. Do you mind elaborating how this code is working? – Generaldeep Oct 14 '22 at 17:27
  • What is it exactly that you don't understand? I will try to elaborate. – Riscie Oct 15 '22 at 18:35
  • I'm confused on how .first+.cdk-overlay-connected-position-bounding-box is working. Is it because of [backdropClass]="'first'"? I tried adding a simple class in the menu container, and then try to isolate the overlay, but it was always impacting the global overlay. Here it's not the class. So, how is the css taking place in isolation here? – Generaldeep Oct 20 '22 at 17:43
  • Exactly, it's because the `[backdropClass]="'first'"` (and `[backdropClass]="'second'"`) add a distinguishable class to the previous sibling of the cdk-overlay class we want to target. This is the reason why we can make use of the selector I wrote within the answer. – Riscie Oct 21 '22 at 12:38
  • Would you mind accepting, if the answer did help you? – Riscie Nov 08 '22 at 08:24
0

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

Eliseo
  • 50,109
  • 4
  • 29
  • 67
  • I understood he wants to target `cdk-overlay-connected-position-bounding-box` specifically, which will not be a child of the `left` and `right` class, because it's appended further up within the dom when opening the menu. – Riscie Oct 13 '22 at 08:28
  • @Riscie, the menu has a property:`overlayPanelClass` adding this property, you can use `.class1 .cdk-overlay-connected-position-bounding-box{...}` (always you need put the class in **styles.scss**, but to control the position of menu it's better used the xPosition and yPosition as the [docs](https://material.angular.io/components/menu/api#MatMenuDefaultOptions) indicate – Eliseo Oct 13 '22 at 08:39
  • I know. But did you try it with `property:overlayPanelClass`? I could not get it to work. – Riscie Oct 13 '22 at 08:54
  • @Eliseo, xPosition is not working, that was the first solution I sought after reading the docs. Also, rendering – Generaldeep Oct 14 '22 at 17:25
  • See the version of Angular and material-angular. And check if you import all the modules you need. – Eliseo Oct 15 '22 at 13:09