angular / components

Component infrastructure and Material Design components for Angular
https://material.angular.io
MIT License
24.35k stars 6.74k forks source link

Scrollable MatMenu disappears on Mobile Safari just after open animation #11677

Open randombumper opened 6 years ago

randombumper commented 6 years ago

Bug, feature request, or proposal:

Bug.

What is the expected behavior?

MatMenu should appear and stay on screen after opening.

What is the current behavior?

MatMenu shows, but just after the fade in animation ends, it becomes invisible. It's still there, and you can still select items, but it's invisible.

What are the steps to reproduce?

https://stackblitz.com/edit/angular-xf5tdi?file=app%2Fmenu-overview-example.html Above example is taken from the official documentation, but instead of two items there are sixteen now.

What is the use-case or motivation for changing an existing behavior?

Which versions of Angular, Material, OS, TypeScript, browsers are affected?

This happens (at least) on iOS 11.2. with Angular 6.0.3, Angular-Material 6.2.0 and Mobile Safari

Is there anything else we should know?

It appears to be Mobile Safari's fault. Changing .mat-menu-panel style to overflow: initial and then back to overflow: auto fixes the issue (that's the workaround I'm using). I'm reporting this here anyhow, since Apple updates their browser once a year at most.

carusog commented 6 years ago

Hi @randombumper and thanks, getting the same issue, and was not able to understanding why it was happening. Btw, how did you get it?

Would you mind to share your quick fix here? It's not clear to me how you fixed it.

In any case, the issue happens also when there is just a toggle as a menu item and not necessarily with a long list of menu items like so:

<button mat-raised-button [matMenuTriggerFor]="appMenu">
    Trigger mat menu with toggle in it
</button>

<mat-menu #appMenu="matMenu" overlapTrigger="false">
    <button mat-menu-item>Click me!</button>
    <button mat-menu-item>Click me!</button>
    <button mat-menu-item>Click me!</button>
    <button mat-menu-item (click)="$event.stopPropagation()">
        <mat-slide-toggle>Slide me!</mat-slide-toggle>
    </button>
</mat-menu>
carusog commented 6 years ago

@randombumper @crisbeto I prepared a sandbox here so that you can test is easily.

Edit: I added a quick fix to the issue by appending to the head element the required styles for mat-panel as explained by @randombumper above. Just bind fixOverflow helper function to the click event on each menu trigger that needs it for now.

abeymg commented 6 years ago

This is affecting our app as well. Update: Using the lazy rendering feature as mentioned in the issue below seems to resolve it

https://github.com/angular/material2/issues/11366

lemoinem commented 6 years ago

We've hit the same issue. Using import "zone.js/dist/zone-patch-rxjs"; in the polyfill as recommended in many issues did not solve our problem and we were already using lazy rendering (so didn't solve our problem either).

carusog's solution DID fix our problem. It's quite the hack, but in the mean time, it works quite well.

adamdport commented 6 years ago

This is still an issue in Material 7.0.0-beta.0 https://stackblitz.com/edit/angular-92bnjh-8nxizv

jbojcic1 commented 6 years ago

Any news on this? Imo this is a pretty big issue and should be addressed asap.

lemoinem commented 6 years ago

FYI: As far as we can tell, the issue has been solved in Safari on iOS 12... But it should still be fixed by Material on previous versions...

JoeOsterfeld commented 5 years ago

This issue seems to be appearing again.

    / \   _ __   __ _ _   _| | __ _ _ __     / ___| |   |_ _|
   / △ \ | '_ \ / _` | | | | |/ _` | '__|   | |   | |    | |
  / ___ \| | | | (_| | |_| | | (_| | |      | |___| |___ | |
 /_/   \_\_| |_|\__, |\__,_|_|\__,_|_|       \____|_____|___|
                |___/

Angular CLI: 7.3.1
Node: 8.11.4
OS: linux x64
Angular: 7.2.4
... animations, common, compiler, compiler-cli, core, forms
... http, language-service, platform-browser
... platform-browser-dynamic, platform-server, router
... service-worker

Package                           Version
-----------------------------------------------------------
@angular-devkit/architect         0.13.1
@angular-devkit/build-angular     0.13.1
@angular-devkit/build-optimizer   0.13.1
@angular-devkit/build-webpack     0.13.1
@angular-devkit/core              7.3.1
@angular-devkit/schematics        7.3.1
@angular/cdk                      7.3.1
@angular/cli                      7.3.1
@angular/fire                     5.1.1
@angular/flex-layout              7.0.0-beta.23
@angular/material                 7.3.1
@angular/pwa                      0.13.1
@ngtools/webpack                  7.3.1
@schematics/angular               7.3.1
@schematics/update                0.13.1
rxjs                              6.4.0
typescript                        3.2.4
webpack                           4.29.0
lemoinem commented 5 years ago

@JoeOsterfeld What version of Safari are you using?

JoeOsterfeld commented 5 years ago

@lemoinem iOS 12.1.4 (Latest). I removed ViewEncapsulation.None from my angular component and it seems to have fixed it, but this means I'm unable to style the menu. Thanks!

ClemensSchneider commented 5 years ago

Can confirm this bug on iOS 11.4.1 using Material 7.2.2 as well as on iOS 12.2 (16E227) using both Material 7.2.2 and latest 7.3.7. Already using ng-template to lazyload contents but only the workaround mentioned above (switching styles from overflow: auto to overflow: initial) fixes the misbehavior.

Added here again for completeness (call on (click)):

fixDisappearIOSBug () {
    const styleNode = document.createElement('style');
    styleNode.type = 'text/css';
    styleNode.id = 'panel-fix';
    styleNode.appendChild(document.createTextNode('.mat-menu-panel{overflow: initial !important;}'));
    document.getElementsByTagName('head')[0].appendChild(styleNode);
    setTimeout(() => {
      styleNode.remove();
    }, 500);
  }
closca commented 5 years ago

Hi, I faced the same issue as the other guys. Mat-menu doesn't stay open on the first tap. I started to look around and check the solutions listed in this thread, and indeed the fix with overflow did work but I didn't consider as good enough to achieve the best User Experience (was flickering). Therefore, I decided to get back to basics, and I was wondering if the official examples face the same issues as we did. They work just fine. From this point was necessarily just a second to see what I was doing wrong. Here is the way how I was writing the HTML:

<mat-menu #menu="matMenu">
  <button mat-menu-item>Item 1</button>
  <button mat-menu-item>Item 2</button>
</mat-menu>
<button mat-button [matMenuTriggerFor]="menu">Menu</button>

And here is the way how is written on the official examples from https://material.angular.io/components/menu/examples

<button mat-button [matMenuTriggerFor]="menu">Menu</button>
<mat-menu #menu="matMenu">
  <button mat-menu-item>Item 1</button>
  <button mat-menu-item>Item 2</button>
</mat-menu>

You can notice that the trigger has to be declared before the menu.

lemoinem commented 5 years ago

In our case, we are already declaring the menu after the trigger... @closca's solution did not solve our issue.

philip-firstorder commented 5 years ago

Reproduced on iOS 12.2 on Safari, Chrome, Firefox, Opera Touch and Edge.

Also it is happening only on submenus, and only the first time I open it.

jpike88 commented 5 years ago

having this issue too. major pain, none of the workarounds listed are working for me. how is this still an open issue

trekmbikes commented 5 years ago

For me the issue was not with the overflow style, it was with the "position: fixed !important" style on mat-menu-panel - if I set that to initial and then back again, the menu appears. I think you can safely add this style to the dynamic style node to solve problems for a larger % of users.

styleNode.appendChild(document.createTextNode('.mat-menu-panel{overflow: initial !important; position: initial !important; }'));

philip-firstorder commented 5 years ago

@crisbeto Can you please set this to a higher prio?

This simple workaround from #11366 by using lazy rendering in nested menus works:

<mat-menu #rootMenu="matMenu">
  <button mat-menu-item [matMenuTriggerFor]="subMenu">Power</button>
  <button mat-menu-item>System settings</button>
</mat-menu>

<mat-menu #subMenu="matMenu">
  <ng-template matMenuContent> <!-- Use lazy rendering for fix Mobile Safari bug -->
    <button mat-menu-item>Shut down</button>
    <button mat-menu-item>Restart</button>
    <button mat-menu-item>Hibernate</button>
  </ng-template>
</mat-menu>

<button mat-icon-button [matMenuTriggerFor]="rootMenu">
  <mat-icon>more_vert</mat-icon>
</button>
btxtiger commented 5 years ago

The issue appeared for me while having transform: translate3d(0,0,0); set in a higher context to force GPU rendering. After removing this everywhere, the menu worked as expected on safari mobile.

rtyx commented 5 years ago

Can confirm this bug on iOS 11.4.1 using Material 7.2.2 as well as on iOS 12.2 (16E227) using both Material 7.2.2 and latest 7.3.7. Already using ng-template to lazyload contents but only the workaround mentioned above (switching styles from overflow: auto to overflow: initial) fixes the misbehavior.

Added here again for completeness (call on (click)):

fixDisappearIOSBug () {
    const styleNode = document.createElement('style');
    styleNode.type = 'text/css';
    styleNode.id = 'panel-fix';
    styleNode.appendChild(document.createTextNode('.mat-menu-panel{overflow: initial !important;}'));
    document.getElementsByTagName('head')[0].appendChild(styleNode);
    setTimeout(() => {
      styleNode.remove();
    }, 500);
  }

This worked for me, but I called it on "onMenuOpened()" - it seems to be a bit more smooth

csidorenko commented 5 years ago

The source of this issue is described here https://github.com/angular/components/issues/11415

am-awais commented 5 years ago

Anyone explain this please as i m newbie here... Changing .mat-menu-panel style to overflow: initial and then back to overflow: auto HOW?

lemoinem commented 5 years ago

@am-awais Check the code provided in https://github.com/angular/components/issues/11677#issuecomment-483598061

As to why it works/is needed: There is a bug in Safari, the CSS isn't applied the way it should be.

jimmykane commented 4 years ago

Hi is this fixed or what?

squelix commented 4 years ago

Issue is back with IOS 13 :/

InterwebCounty commented 4 years ago

For me, I had a blur filter on it: (backdrop-filter: blur(6px);) When I removed it (and used the ng-template lazy rendering and did the fixDisappearIOSBug thing for good measure) it worked. No idea why the blur was messing it up, maybe it's a clue.

hunterjenkins commented 4 years ago

Wrapping my menu inside of an ng-template (see post above) fixed the issue for me.