Components: position mat-menu in right side of the trigger

Created on 24 Dec 2018  路  14Comments  路  Source: angular/components

Please describe the feature you would like to request.

I would like to have option to open mat-menu in right side of the trigger.

It should look like below

image

while as per current design it is looking like as below
image

What is the use-case or motivation for this proposal?

I want to create overlay which should not overlap other menuitems in sidemenu and should render in right side of the trigger.

Is there anything else we should know?

Here is sample stackblitz
https://stackblitz.com/edit/angular-wurasp

I also tried with custom overlay but in that also there are only three options

for Xposition start, center and end
for Yposition top, center, bottom

I tried with xPosition end and Yposition center but not able to get what I want.

P4 materiamenu feature

Most helpful comment

You can use matMenuTrigger and matMenuTriggerFor to achieve this.

https://stackblitz.com/edit/angular-material-menu-position-aside

All 14 comments

Any update on this ?

In order for this to work, you have to change the way the setPosition method of the MatMenuTrigger works. Something like this:

  private setPosition(positionStrategy: FlexibleConnectedPositionStrategy) {
    let [originX, originFallbackX]: HorizontalConnectionPos[] = this.menu.xPosition === 'left' ? ['start', 'end'] : ['end', 'start'];
    let [originY, originFallbackY]: VerticalConnectionPos[] = this.menu.yPosition === 'top' ? ['top', 'bottom'] : ['bottom', 'top'];

    let [overlayX, overlayFallbackX]: HorizontalConnectionPos[] = ['start', 'end'];
    let [overlayY, overlayFallbackY]: VerticalConnectionPos[] = this.menu.yPosition === 'top' ? ['top', 'bottom'] : ['bottom', 'top'];

    let offsetY = 0;

    if (this.triggersSubmenu()) {
      // When the menu is a sub-menu, it should always align itself
      // to the edges of the trigger, instead of overlapping it.
      overlayFallbackX = originX = 'end';
      originFallbackX = overlayX = 'start';
      originFallbackY = overlayY = overlayFallbackY = originY = 'top';
      offsetY = -MENU_PANEL_TOP_PADDING;
    } else if (!this.menu.overlapTrigger && originY === 'bottom') {
      overlayY = 'top';
      originFallbackY = 'bottom';
    }

    positionStrategy.withPositions([
      { originX, originY, overlayX, overlayY, offsetY },
      { originX: originFallbackX, originY, overlayX: overlayFallbackX, overlayY, offsetY },
      {
        originX,
        originY: originFallbackY,
        overlayX,
        overlayY: overlayFallbackY,
        offsetY: -offsetY
      },
      {
        originX: originFallbackX,
        originY: originFallbackY,
        overlayX: overlayFallbackX,
        overlayY: overlayFallbackY,
        offsetY: -offsetY
      }
    ]);
  }

Also:

export type MenuPositionX = 'left' | 'right';
export type MenuPositionY = 'top' | 'bottom';

This way, the menu by default will still open the same as before, but if you use xPosition="right" yPosition="top", it will open to the right of the trigger.
screenshot 2019-03-01 at 15 46 03

Thanks @jpzwarte. I saw this method but was not able to override as its private method. Did you find any way to override it?

The more i think about it the more i think the API needs to be different something like: [position]="['right', 'top']" where the first position is the primary position and the second the secondary, so:

  • right, top: right side of the trigger, align to top of trigger
  • top, right: top side of the trigger, align to right of trigger
  • bottom, left: bottom side of the trigger align to left of trigger
    etc.

@lokeshdaiya i'm working on a custom menu component (not OSS). So using material as inspiration.

I've written the code that implements the behavior in my previous comment: https://gist.github.com/jpzwarte/5b6f848a8cbc1488779181894382f306

Feel free to use the code however you see fit (cc @crisbeto)

@jpzwarte Have some stackblitz example? I tried to use your API but something got wrong.

Any update on this feature? I see this lacking in angular mat-menu which is very common usecase and need.

@jpzwarte what/where do I get the method triggersSubMenu()? Also, how do you even use this? I know it's supposed to be a directive but other than that I know nothing else.

This would be a nice feature

Until the material team up the priority for this feature and actually implements it, here is an example that emulates the behavior using the existing API...

https://stackblitz.com/edit/material-menu-right-position

You may want to add some css and codes to fine tune its appearance and behavior. For example, automatically expand the nested submenu when parent menu is clicked, etc.

Hope this helps.

https://stackblitz.com/edit/material-menu-right-position

@okeydoky Your url appears to be incorrect, it points to the repo issues page.

@rafaelss95 Thanks for noticing. I updated the url.

You can use matMenuTrigger and matMenuTriggerFor to achieve this.

https://stackblitz.com/edit/angular-material-menu-position-aside

@nzbin
I had the same idea, but when the element is at the bottom of the page, the menu will open above the trigger

Was this page helpful?
0 / 5 - 0 ratings

Related issues

xtianus79 picture xtianus79  路  3Comments

crutchcorn picture crutchcorn  路  3Comments

jelbourn picture jelbourn  路  3Comments

shlomiassaf picture shlomiassaf  路  3Comments

Miiekeee picture Miiekeee  路  3Comments