components
components copied to clipboard
bug(tabs / mat-tab-group): Open dialog with component mat-tab-group and fast change mat-tab (click another mat-tab) and empty content
Is this a regression?
- [ ] Yes, this behavior used to work in the previous version
The previous version in which this bug was not present was
No response
Description
If I open a dialog in which I have a mat-tab-group component and quickly click on another tab (another mat-tab), the content of the newly opened tab is not rendered - it remains empty. It looks right in DOM.
There are several ways to quickly change a tab:
- By touch
- Click the mouse
- By entering the click command in the console: document.evaluate('//html[1]/body[1]/div[1]/div[2]/div[1]/mat-dialog-container[1]/dialog-data-example-dialog[1]/div[1]/mat-tab-group[1]/mat-tab-header[1]/div[1]/div[1]/div[1]/div[2]', document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue.click()
Fast click on tab after dialog open - bug

Slow click on tab after dialog open - correct

Reproduction
Steps to reproduce:
- https://stackblitz.com/edit/angular-k1g4u3-pmsayf
Expected Behavior
Correctly loaded content of the newly selected tab
Actual Behavior
The empty content of the newly selected tab
Environment
- Angular: 14.0.0
- CDK/Material: 14.0.4
- Browser(s): Google Chrome 103.0.5060.66
- Operating System (e.g. Windows, macOS, Ubuntu): Windows
Maybe there will be a problem in the animation. Because when I added [@.disabled]="true" animationDuration="0" to the mat-tab-group, the content is always rendered
Before - with empty content mat-tab-group
Then - everything is fine <mat-tab-group [@.disabled]="true" animationDuration="0">
Most important is [@.disabled]="true"
I was able to reproduce on Chrome
Chrome/Chrome OS Version 102.0.5005.75 (Official Build) (64-bit)
I spent some time debugging it and this seems like an issue either in the browser or in the Angular animations module, or some combination of both. I tried diffing the DOM between the broken and working states and it was identical, however for some reason the .mat-tab-body-content of the current tab has visibility: hidden, even though nothing is actually setting it. Even if I add visibility: visible !important through the dev tools, the element still doesn't render.
@crisbeto I also tried to change the visibility manually using dev tools, and saw the same behavior. The problem for me was this rule:
.mat-mdc-tab-body-content[style*="visibility: hidden"] {
display: none;
}
I was then able to show the content every time using the following override:
.mat-mdc-tab-body-content[style*="visibility: hidden"] {
display: block !important;
}
My context for this bug is somewhat different. I am using a mat-tab under a mat-menu, but I think we are seeing the same issue due to the overlay. I see the behavior after closing and opening the mat-menu 2 times. Then changing the tab results in empty content.
I was able to workaround the issue, but lose animations by setting the animationDuration to 0 and overriding the styles:
Template:
<mat-menu #menu="matMenu">
<mat-tab-group (click)="$event.stopPropagation()" animationDuration="0">
<mat-tab label="1"> Content 1 </mat-tab>
<mat-tab label="2"> Content 2 </mat-tab>
<mat-tab label="3"> Content 3 </mat-tab>
</mat-tab-group>
</mat-menu>
Styles (at the root aka styles.css):
.mat-mdc-tab-body-content[style*="visibility: hidden"] {
display: block !important;
}
.mat-mdc-tab-body-content {
visibility: visible !important;
}
Here is a stackblitz example with my workaround: https://stackblitz.com/edit/angular-umvjvd?file=src/app/menu-overview-example.html
There is a special note regarding the animation and visibility rule in https://github.com/angular/components/blob/main/src/material/tabs/tab-body.scss
Usually the
visibility: hiddenadded by the animation is enough to prevent focus from entering the collapsed content, but children with their ownvisibilitycan override it. This is a fallback that completely hides the content when the element becomes hidden. Note that we can't do this in the animation definition, because the style gets recomputed too late, breaking the animation because Angular didn't have time to figure out the target height. This can also be achieved with JS, but it has issues when starting an animation before the previous one has finished.
I'm using the latest angular but with legacy material components, and I have the same issue.
When the menu is first opened everything is great, but if u close it and open again the animation is bugged for the first time and then goes back to normal.
I tried to do your workaround but to no end :(
+1
+1
+1