Bug.
A <md-expansion-panel [expanded]="false">
should not be expanded until explicitally opened.
When inside a hidden tab, .mat-expansion-panel-content
should have height : 0px
Panel is collapsed but panetl's content is visible. Problem occurs only if the accordion is in a hidden tab of a tab-group.
http://plnkr.co/edit/q6kXPH?p=preview
<md-tab-group>
<md-tab label="Working">
<md-accordion>
<md-expansion-panel [expanded]="false">
<md-expansion-panel-header>
You should see me
</md-expansion-panel-header>
<p>Yous should not see me</p>
</md-expansion-panel>
</md-accordion>
</md-tab>
<md-tab label="Not working">
<md-accordion>
<md-expansion-panel [expanded]="false">
<md-expansion-panel-header>
You should see me
</md-expansion-panel-header>
<p>Yous should not see me</p>
</md-expansion-panel>
</md-accordion>
</md-tab>
</md-tab-group>
Material2 master
Angular 4.2.3
It seems to be working correctly here: http://plnkr.co/edit/q6kXPH?p=preview
correct. It's also working in another page of mine. Currently trying to isolate the pb.
Ok, i edit the issue : the problem occurs only if the element is in a hidden tab. Thanks @julianobrasil
OK. Updated the plunker to reproduce it: http://plnkr.co/edit/q6kXPH?p=preview
Put it in the issue.
This actually happens to anything that contains an animation when set inside a hidden md-tab.
This seems to be caused by angular 4.2 changes.
I use Teradata Covalent expansion panels in my app which have the same problem since the new angular version: https://gitter.im/Teradata/covalent?at=593e58f06549436c7d3c8360
:wink: A very unacceptable workaround (but useful if you can't wait for the next release, possibly without this bug) is using a *ngIf and just show the accordion/expansion panel when it's needed (if it's needed when the page is loaded, put a variable in a setTimeout
to trigger *ngIf
in about 4 to 5 seconds after the tab-group has been rendered, or use the tab change event). In this case the expansion is shown in its expected state (collapsed or expanded).
Hey! that bug is really annoying, is there any hope to see it's fix?) Maybe applying @julianobrasil solution with *ngIf=isActive on tabs content?
@lebeker, I've been using something like that in a project: http://plnkr.co/edit/YAi6Xb?p=preview
I tried isActive (*ngIf="mdTab.isActive"
where mdTab is a reference template variable), but it causes a "changed after checked" error.
Hello! @julianobrasil, following @lebeker advice that's working for me as a workaround:
<md-tab-group [(selectedIndex)]="selectedTabIndex">
<md-tab label="First">
<div>...</div>
</md-tab>
<md-tab label="Second">
<div *ngIf="selectedTabIndex == 1">...</div>
<md-tab>
<md-tab label="Third">
<div *ngIf="selectedTabIndex == 2">...</div>
<md-tab>
</md-tab-group>
@lula worked for me, thanks!
@lula Can you show your component.ts file?
@michalmw there's nothing to show in my component.ts concerning with my workaround. Variable selectedTabIndex
is directly used in the view template. Angular should take care of instantiating it. Should you need to start with another tab than the first, then you can also add selectedTabIndex
to component.ts and set the tab index you prefer. Let me know if this is what you wanted to know or you needed something else :)
Just a little tweak of @lula's solution - you don't need to actually store the selectedIndex
. Instead you could just reference the md-tab-group
:
<md-tab-group #myTabGroup>
<md-tab label="First">
<div>First</div>
</md-tab>
<md-tab label="Second">
<md-accordion *ngIf="myTabGroup.selectedIndex == 1">
<md-expansion-panel *ngFor="let i of [1,2,3];">
<md-expansion-panel-header>
<md-panel-title>Test {{ i }}</md-panel-title>
</md-expansion-panel-header>
<p>Testing content {{ i }}</p>
</md-expansion-panel>
</md-accordion>
</md-tab>
<md-tab label="Third">
<div>Third</div>
</md-tab>
</md-tab-group>
Or use css ? It worked for me ! :)
div.mat-expansion-panel-content:not(.mat-expanded) {
height: 0px !important;
visibility: hidden !important;
}
.mat-expansion-panel-header {
height: 48px;
}
The CSS solution by @bastienlemaitre is not working for me in the content of hidden tabs.
Tried the solution of mdTab.isActive
based on @julianobrasil suggestion with ngIf
but resulting in
ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value: 'false'. Current value: 'true'.
I have to generate tabs dynamically, so storing selected index won't work. Here is what I am trying.
<mat-tab-group #tabGroup>
<mat-tab #currTab *ngFor="let label of labels">
<ng-template mat-tab-label>
<span>{{label}}</span>
</ng-template>
<div *ngIf="currTab.isActive" >
<mat-expansion-panel [expanded]="false" *ngFor="let panel of panels">
<mat-expansion-panel-header>
<mat-panel-title>{{panel.title}}</mat-panel-title>
<mat-panel-description>{{panel.desc}}</mat-panel-description>
</mat-expansion-panel-header>
<div>{{panel.content}}</div>
</mat-expansion-panel>
</div>
</mat-tab>
</mat-tab-group>
Is there a better way to operate on this one?
@rayabhagis, try @lula solution above (https://github.com/angular/material2/issues/5269#issuecomment-326692430). It's simple and dosen't throw the "changed after checked" error.
Thanks, I updated my code to follow similar approach by comparing index of *ngFor on tabs with tab-group's selectedIndex and there is no "change after checked" error.
@rayabhagis, did you use this into your component ?
encapsulation: ViewEncapsulation.None
Updated CSS:
div.mat-expansion-panel-content:not(.mat-expanded) {
height: 0px;
visibility: hidden;
}
.mat-expansion-panel-header:not(.mat-expanded) {
height: 48px;
}
.mat-expansion-panel-header {
height: 64px;
.mat-content {
font-weight: 100;
font-size: 18px;
}
&.mat-expanded {
.mat-expansion-indicator {
transform: rotate(180deg);
}
}
}
Apparently the problem is on trigger animation.
The trigger isn't call when component is inside a false *ngIf.
I don't know if this is a problem in Material or Angular.
Any update on this? Still broken in angular 5.0.0 with material 5.0.0-rc0 for me :( I have an expansion panel inside of a tab. When I navigate to the tab, I can see the contents of the expansion panel, instead of the contents being hidden.
@rhino5oh the solution by @lula at https://github.com/angular/material2/issues/5269#issuecomment-326692430 worked for me.
<mat-tab-group class="mat-elevation-z3 bg-white" [(selectedIndex)]="selectedTabIndex">
<mat-tab label="Edit Details">
<app-group [audit]=audit [group]=group></app-group>
</mat-tab>
<mat-tab label="Manage Criteria">
<app-group-criteria [audit]=audit [group]=group [visible]="selectedTabIndex == 1"></app-group-criteria>
</mat-tab>
</mat-tab-group>
@ianjoneill While that is a solution I don't think the intention is to require that by default in the tab section.
It's certainly not in the docs that it's required.
Unfortunately, the solution with *ngIf="selectedIndex === 1"
doesn't work if you need forms inside your tabs as if the user change tabs, it'll destroy your components with your FormControl's values.
Angular 5 + latest material: still able to reproduce the bug :(
But @lula workaround helped to solve the issue.
https://github.com/angular/material2/issues/5269#issuecomment-326692430
Hopefully we will have a real fix soon
the solution by @lula worked for me.
Did something change here? The solution that was working earlier seems to have broken in our app now.
I can confirm this. Upgrading from @angular/[email protected] to @angular/[email protected] unfortunately invalidated the workaround mentioned above.
@julianobrasil - thoughts?
Note: The suggestion by @bastienlemaitre seems to be still valid.
I call a function in selectedTabChange
and, inside this function:
setTimeout(() => this.showExpansion = true, delay);
and
<mat-expansion-panel *ngIf="showExpansion">
If I remember it right, the problem occured just in the first time a tab content became visible. Dispite of that I used to switch the showExpansion
back to false when it became hidden again.
@ClemensSchneider sad but true. That trick stops working with @angular/[email protected].
@julianobrasil just playing along with your solution but it didn't work in my case with more than two tabs. I believe that's because the showExpansion
property is not actually changed after the first tab change. Changing it just before setTimeout had no effect for me. Perhaps I did something wrong?
To have my test working with more than two tabs I basically just changed the type and the name of the property selectedTabIndex
(of course 鉂わ笍 ). Here it is:
export class AppComponent {
selectedTabIndex = 0;
tabChange(event) {
Promise.resolve().then(() => this.selectedTabIndex = event.index);
}
}
<mat-tab-group (selectedTabChange)="tabChange($event)">
<mat-tab label="Tab 1">
<mat-expansion-panel>...</mat-expansion-panel>
</mat-tab>
<mat-tab label="Tab 2">
<mat-expansion-panel *ngIf="selectedTabIndex == 1">...</mat-expansion-panel>
</mat-tab>
<mat-tab label="Tab 3">
<mat-expansion-panel *ngIf="selectedTabIndex == 2">...</mat-expansion-panel>
</mat-tab>
</mat-tab-group>
Cheers!
Is there any news on whether this issue will be addressed in a forthcoming release?
@lula's workaround still works for me as of today, but hopefully its fixed soon
@lula Your workaroud is working perfectly
I don't know how they could release with a bug this big.
Hi @Sieabah,
Angular Material was release as release candidate
so developers could help to test in different scenarios to find more bugs.
@leocaseiro Right, it was more about how it couldn't be promoted from RC until it is fixed.
I can confirm that neither mat-accordion nor mat-expansion-panel are causing the issue. This is because I'm having the same exact problem using PrimeNG's p-accordion and p-accordionTab. Hopefully that helps save some debug time for the devs.
@lula, your fix almost work perfectly. In my case I was just missing the selectedIndex <mat-tab-group [(selectedIndex)]="selectedTabIndex" (selectedTabChange)="tabChange($event)">
which seems to make difference for some reason. Anyway thanks for saving my day !
in component:
selectedTab: MatTab;
in template:
<mat-tab-group (selectedTabChange)="selectedTab=$event.tab">
...
<mat-tab #mdTab label="Super Label">
<div *ngIf="mdTab==selectedTab">
...
@rhino5oh You're exactly right, I'm having this same type of issue using ngx-datatable. The table literally disappears when I change to the proper tab. When I change back to the first tab the table that was once appearing is gone too. When you click the tab and the tab navigation starts you can see it flash into view as the animation takes it out of view.
Unfortunately, for me @lula 's solution had to be modified slightly to declare a class property in my component called selectedIndex
because it wasn't inherently creating that local variable in the template... not sure when that changed. But other than that minor change this method worked for me as well, thank you.
Our project is using @angular/material: 5.0.1 and angular 5.1.0.
I'm seeing this same issue with @angular/material 5.0.4 and @angular 5.1.1
@lula's solution doesn't work for me. Only the initial tab renders correctly and only until you change tabs.
@bastienlemaitre CSS solution does appear to work for me. Although I had to add a :host /deep/ to each entry, for it to work in the target component.
Hi here!
Any update regarding an eventual schedule for this fix?
@JKing-B16 it seems to work properly with angular 5.1.1. See this plunker I just created.
@lula You are using the workaround suggested above (<mat-expansion-panel *ngIf="selectedTabIndex == 3">
), that is not really a fix because:
Still waiting for a follow up on this.
@boris-marinov I know it is a workaround, I never said it was a fix. See my plunker tabs animations seem to work.
I can confirm the workaround provided by @lula works! It already saved me for my next push in production :-D But yeah a real fix would be welcome ^^
Seems that it's not an issue with the material expansion-panels (as @rhino5oh already noted), but a general issue with angular animations that have a target height of *
and are triggered while the element to be animated is still detached from DOM (and thus, the target height cannot be known). I can confirm that my own components that include such animations are rendered incorrectly (height = 0) when used inside tab-content.
Maybe somebody from the material-team can confirm this assumption?
It looks like PR #8921 will bring some light to this issue.
@ClemensSchneider I can confirm that! The bug occurs on my custom components with animations properties like "height: '*'" inside a tab content.
Solution with *ngIf and tab.isActive or tabs.selectedIndex == 1 gives me error and not working
ERROR TypeError: Cannot read property 'name' of undefined
at checkBindingNoChanges (vendor.bundle.js:73024)
at checkNoChangesNodeInline (vendor.bundle.js:77073)
at checkNoChangesNode (vendor.bundle.js:77047)
at debugCheckNoChangesNode (vendor.bundle.js:77876)
at debugCheckDirectivesFn (vendor.bundle.js:77778)
But css solution @bastienlemaitre works perfect for me.
material 5.1.1
Hey, guys! Good news. This is fixed in 6.0.0-beta.0
: https://stackblitz.com/edit/angular-material2-beta-6-table-mat-tab
To use the lazy loading feature, just put mat-tab
content inside <ng-template matTabContent>
<mat-tab label="Lazy loading content">
<ng-template matTabContent>
<!--here goes tab content-->
</ng-template>
</mat-tab>
Thanks @julianobrasil , I'll have to try that.
I gotta say, the whole "ng-template matTabContent" is documented poorly. No mention of it here (where I really think it should be mentioned): https://material.angular.io/components/tabs/api
However, I did find it here: https://github.com/angular/material2/blob/master/src/lib/tabs/tabs.md ...but that wasn't until I read julian's post and knew what to google for in order to find it.
The docs site will be updated for sure when the final release is out. I don't think the team is updating the site for beta/rc versions.
@julianobrasil Do the 6.0.0 introduces any breaking changes? Changelog doens't says anything.
I haven't seen any until now. But it's not an assurance that there won't be any. Now it's kind of hard to figure out whether there are breaking changes based on version major number changes as it appears it'll be updated following angular versions (material will follow angular version even if it doesn't change a thing, so angular versions would be the main breaking changes).
Thank's. I did upgraded without any visible/testable issues, and the problem is also fixed.
For those who want to upgrade, first upgrade angular to latest using:
ng update --next
then change your @angular/cdk
and @angular/material
to 6.0.0-beta.2
My Tabs content is dynamically loaded so even using matTabContent
with the latest beta (6.0.0-beta.4
) couldn't work for me. CSS solution works perfectly except for the keen eyed who will notice the content disappearing before the expansion panel collapses completely.
@macjohnny, could you provide a working stackblitz demo to show your case?
Hey @julianobrasil I assume you were referring to me 馃槈
My situation is something along these lines.
Hopefully you'll notice some implementation path I missed!
hahaha I was indeed referring to you @jonyadamit.
Hey @jonyadamit I changed you code a little bit. its working now. Your Tabs content is dynamically loaded, I hard coded the accordion there and put some logic.
I don't know you logic in details that's why I hard coded.
I hope you will be able to make it according to your need and will be help full.
Actually in my case, its working with Material 5.1.0 version.
@anurag-itsolvs - this appears to show a different bug;
Lazy-rendering expansion panels breaks unless also lazy-rendering tab-content.
I forked your working link and made two changes:
<ng-template matExpansionPanelContent><span>
You shouldn't see me yet!</span></ng-template>
<div *ngIf="selectedIndex == 1">
to remove lazy-rendering of tabs.These changes are useful when the tab content should be loaded normally (i.e. no lazy rendering) - but keep expansion panels lazy-loaded for performance.
Unfortunately, mat-expansion-panel-header renders incorrectly. I've added orange background to show the incorrect height.
Expanding the panel corrects the mat-expansion-panel-header to the proper height:
...and finally collapsing the panel, the height remains correct:
@jonyadamit, sorry for the huge delay. It's been a very busy time for the last two weeks and I had completely forgotten to take a look at your stackblitz link.
There's another solution to your problem, by using CdkPortal
s (I'm not sure why ViewChildren
is apparently ignoring itemHost
in your stackblitz sample. I think it's just a matter of setup the pieces on the template.)
Using CdkPortal
s: I've put together a stackblitz example => https://stackblitz.com/edit/tabs-hidden-tabs-do-render-corretly
I've posted this on StackOverflow in case it's just my implementation. is-mat-expansion-panel-lazy-rendering-broken
@jackwootton I have changed your code a bit. its working properly.
The problem is all about *ngIf. First time its not able to make it true. that's why I am setting it true using setTimeout().
If you still have issue do let me know. I will try to help.
@anurag-itsolvs - The problem is, this approach caused the component to be destroyed and initialized every time the user selects a different tab (i.e. ngOnInit and ngOnDestroy are repeatedly run). I'm looking to keep the tab loaded eagerly, but expansion panel's within the tab should be loaded lazily.
@julianobrasil thanks, looks good, I'll switch to using your example! Still wonder why it didn't work the original way..
@anurag-itsolvs thanks for trying to help too, but since you hard-coded the content it lost it's original intention. @julianobrasil's example is the way to go about this.
@julianobrasil unfortunately this method means the tab's content gets destroyed when navigating away, and re-created when clicking again, which is not suitable for all cases..
What's more, this really feels like a workaround rather than a fix.
Is there a plan to fix this rendering issue without needing to use lazy rendering?
Ultimately I resorted to using @jackwootton 's matExpansionPanelContent
suggestion but there is still some rendering issue as he suggests, until the panel is expanded and collapsed again.
@jonyadamit, yeah, this is drawback of this way. I really don't know about where this is in material project timeline, but my guess is that this is actually an angular issue instead of a material one and matTabContent
is a feature that can be used to fix this issue in some specific cases (when you don't need to keep the state).
The CSS solution is working for me, but there is an ugly jump in the animation.
Is there any way to fix this jump within CSS? Tried a few things, but it looks like that the height change gets not animated properly.
Anyways can't wait to see a true fix for this annoying bug.
As a working workaround for lazy initialized panels i propose following CSS
.mat-expansion-panel-header {
height: 48px;
}
.mat-expansion-panel-content:not(.mat-expanded):not(.ng-animating){
display: none;
}
For some reasons bastienlemaitre's solution was breaking animiation in my case. After trial and errors this isw what I came up with. Animation is still not that smooth on panel collapse, but its better then whole content poping upon expansion.
@TobiasMalikowski probably this will help you.
@Antoniossss Thanks mate, that workaround looks smoother. Hope this gets fixed soon, so no workaround is needed.
confirm that the trick from @julianobrasil using
works well on material 6 :-)
has a fix been posted yet? still seeing this in 6.2.1...
If it's not it's amazing that it's still not fixed.
Yes sadely fix is still not in...
@TobiasMalikowski - Try setting the collapsedHeight
and expandedHeight
to the same values (use MatExpansionPanelHeader).
Although this changes the look and feel a little, it does prevent any nasty jumps.
<mat-expansion-panel-header collapsedHeight="48px" expandedHeight="48px">
...
</mat-expansion-panel-header>
ok what i had to do was use lazy loading and then it works better still not perfect and hovering over the title, the height does not get set until its expanded/collapsed
How about MAT team fix the bug and we will not have to look for not-working-anyway workarounds ?:)
I think its high time, the Mat team fix this asap. please put a fix in.
I think the issue needs to ferment for another year before we should get a fix.
@Sieabah lol
This really needs to be fixed.
The following scss worked for me as a workaround:
.mat-expansion-panel-header {
height: 48px;
}
.mat-expansion-panel-content:not(.mat-expanded) {
.mat-expansion-panel-body {
padding-bottom: 0;
}
}
@Sieabah instead of making pointless comments, why not simply submit a pr with a fix? or maybe dig into the issue and try to found out what is exactly causing it?
@jotatoledo I'd love to submit a PR, but I unfortunately don't have the time to figure it out nor the desire to. I started using primeng instead of angular-material after the entire api changed out from under me 4 times.
Hey, i just temporarily fixed this error for me by adding click event on mat-tab, and checking for right index.
Like this:
(selectedTabChange)="showAccordion($event)"
and in function switch right bool:
showAccordion(event) {`
if (event.index === 1) {
setTimeout(() => {
this.showAccordionBool = true;
}, 100);
} else {
setTimeout(() => {
this.showAccordionBool = false;
}, 100);
}
}
And lastly added in my template that if statement:
<mat-accordion *ngIf="showAccordionBool">
Since Angular 6 mat-tabs can be loaded lazily. Example: (from StackOverflow)
<mat-tab-group>
<mat-tab>
<ng-template matTabContent>
<p>Content goes here</p>
</ng-template>
</mat-tab>
</mat-tab-group>
This should solve the issue.
I fixed this by modifying polyfills.ts and uncommented web-animations.js after installing the npm package.
Best solution for me is DamienFlury solution because also works with your custom animations and without css
@DamienFlury
Sam problem here, solved with your method, thanks~!!!
I have the same problem.
Acordion in all overlay after first open is destored.
@DamienFlury thank you for you solution man!
@DamienFlury - This doesn't appear to work when dynamicHeight="true"
on mat-tab-group
because:
This causes an unsightly flicker each time the tab is loaded.
can mat-expansion-panel-content actually be selected? I have tried to select it, and never worked...
I did a simple test to put a backgroud-color in mat-expansion-panel-body and it never show up anything. And no matter what I put in there, never worked.
But mat-expansion-panel-header always works...
Could you pls let me know how you manage to select it successfully in scss file?
.mat-expansion-panel-content:not(.mat-expanded) {
.mat-expansion-panel-body {
background-color: blueviolet;
padding: 0;
}
}
}
Hi guys,
I think the problem is solved on material version 7.
I had the problem on version 6 and I used the CSS trick explain by @bastienlemaitre which worked. But after the upgrade to v7, the CSS was atually breaking the expansion panel. So I removed the CSS and now the expansion panel is working perfectly inside the mat-tab without any tricks.
I can confirm the problem is resolved on material version 7.
Thank you @BobBDE for pointing me to the breaking CSS (couldn't remember where that workaround was - which I suspected was causing my content to disappear..).
by the way.. you can easily confirm issue resolved by going to my demo for this issue, see it as it is, update dependencies, reload - and see everything works fine!
im still having the issue
I just fixed it by lazy loading the non-default tab.
https://material.angular.io/components/tabs/overview#lazy-loading
6/7
Applying your own animations does not work, where you put the animation the control disappears
Issue still exists in version 8.
When will this library be comparable to the material-ui that react has?
React currently has a better material component library than Google's own material library
This is not specific to MatTab, it is happening when accordion is embedded
Also in MatTree MatTable etc.
+1
This worked for me
:host /deep/ .mat-expansion-panel-content:not(.mat-expanded) {
height: 0;
visibility: hidden;
}
:host
/deep/
.mat-expansion-panel-header:active
:host
/deep/
.mat-expansion-panel-content.mat-expanded {
visibility: visible;
}
If we don't want to upgrade the angular version
Most helpful comment
Hello! @julianobrasil, following @lebeker advice that's working for me as a workaround: