简体   繁体   中英

Angular Material mat-menu-item to be the same size as the mat-menu button

I use mat-menu of Angular Material with different mat-menu-item and I would like the list of menu items to be the same size as the button.

That's what I have:

在此处输入图片说明

And what I wish:

在此处输入图片说明

I tried to change the size of the menu with the css, but it does not work properly.

CSS:

.cdk-overlay-pane {width: 100%;}
.mat-menu-panel {width: 100%;}

HTML:

<button mat-raised-button [matMenuTriggerFor]="menu" class="btn-block btn-blue">
  <div fxLayout="row" fxLayoutAlign="center center">
    <mat-icon>more_vert</mat-icon>
    <span fxFlex>OPTION</span>
  </div>
</button>

<mat-menu #menu="matMenu">
  <button mat-menu-item>
    <mat-icon>unarchive</mat-icon>
    <span>First</span>
  </button>
  <button mat-menu-item>
    <mat-icon>file_copy</mat-icon>
    <span>Second</span>
  </button>
</mat-menu>

I did a StackBlitz HERE for my mat-menu.

Thank you in advance!

EDIT : I changed my code because I'm using a responsive button with the bootstrap class "btn-block".

Use ::ng-deep to style .mat-menu-panel

::ng-deep .mat-menu-panel {
  padding: 0 10px!important;
  width: 100%!important;
}

See working code

I found a solution really not clean, but here it is:StackBlitz HERE

If someone would have a CSS solution, I'm interested.

HTML:

<button mat-raised-button [matMenuTriggerFor]="menu" class="btn-block btn-blue" id="button">
  <div fxLayout="row" fxLayoutAlign="center center">
    <mat-icon>more_vert</mat-icon>
    <span fxFlex>OPTION</span>
  </div>
</button>

TS:

export class AppComponent implements DoCheck{
  ngDoCheck(){
    var widthButton=document.getElementById("button").offsetWidth;

    var elems = document.getElementsByClassName('mat-menu-panel');
    for(var i = 0; i < elems.length; i++) {
      elems[i].style.width = widthButton+"px";
    }
  }
}

CSS:

.cdk-overlay-pane {width: 100%!important;}
.mat-menu-panel {max-width: 100%!important; min-width: 64px!important;}

DEMO:

在此处输入图片说明

Use menuOpened event for matMenuTriggerFor and add width runtime

HTML :

<button mat-raised-button [matMenuTriggerFor]="menu" class="btn-block btn-blue"  (menuOpened)="onMenuOpened()" id="button">
  <div fxLayout="row" fxLayoutAlign="center center">
    <mat-icon>more_vert</mat-icon>
    <span fxFlex>OPTION</span>
  </div>
</button>

TS :

onMenuOpened() {
    const btn = document.getElementById('revisitSection');
    if (btn) {
      const elems = document.getElementsByClassName('button') as any;
      // for (let i = 0; i < elems.length; i++) {
      //   elems[i].style.width = `${btn.offsetWidth}px`;
      // }
      for (const item of elems) {
        item.style.width = `${btn.offsetWidth}px`;
      }
    }
  }

I don't recommend to use ngDoCheck. it has more performance issue.

For those searching this in the future your can set this in your

.mat-menu-panel {
  min-width: fit-content !important;
  padding: 0px 0px !important;
}

.cdk-overlay-pane {
  min-width: fit-content;
}

To make the mat-menu dynamic then you can apply with and styling in the component css of ts file through [ngClass]="getClassWithWidthandHieght()".Through css set the class of the in side div to the class like this the apply the styling set you styles.

.example-panel{

min-width: 500px; }

In case somebody still needs this. Here is my solution

The idea is to read matMenuTriggerFor clientWidth, pass it to the menu itself as matMenuTriggerData, and bind it to the wrapper width

Since ::ng-deep is going to be deprecated,

https://angular.io/guide/component-styles#deprecated-deep--and-ng-deep

another trick is to create margin around text span (mx-4 is bootstrap class for margin left and right

  <button mat-menu-item>
    <mat-icon>file_copy</mat-icon>
    <span class="mx-4">Second</span>
  </button>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM