Open the first attached expansion panel in an Angular Material accordion

32,844

Solution 1

You can use first variable, I made an stackblitz, you can see here.

You can do as this way:

<mat-accordion class="example-headers-align">
  <mat-expansion-panel *ngFor="let item of [1,2,3]; first as isFirst" [expanded]="isFirst">
    <mat-expansion-panel-header>
      <mat-panel-title> {{item}} </mat-panel-title>
    </mat-expansion-panel-header>
    {{item}}
  </mat-expansion-panel>
</mat-accordion>

You can see here the use of the *ngFor variables for more information.

Solution 2

Have you tried using the ngFor "first" local variable? In this way:

<mat-accordion>
    <mat-expansion-panel *ngFor="let elem of elements; let isFirst = first" [expanded]="isFirst">
         <!--- Something Here --->
    </mat-expansion-panel>
</mat-accordion>
Share:
32,844

Related videos on Youtube

Aaron Hazelton
Author by

Aaron Hazelton

Updated on September 22, 2021

Comments

  • Aaron Hazelton
    Aaron Hazelton over 2 years

    Obviously you can use the input expanded on an Angular Material expansion panel to default a particular panel to be opened upon loading. However, I have an accordion where all of the expansion panels are generated dynamically, and all are optional, but I would like for the first panel to be opened.

    I could go through each of my ngFors that use templates to generate the panels to see if it exists and then on the first index add the attribute, but there are several loops that pull in templates and it seems messy. I would like to be able to grab some property from the mat-accordion after the view has completed to see which is the first one attached to the accordion and add the attribute, but it looks like it isn't possible. Anyone know if there is some way to do this?

  • Aaron Hazelton
    Aaron Hazelton over 5 years
    Good point, I forgot about isFirst and was going to use the index, but that would still mean I have to do needless if checks because as I mentioned there are multiple ngFors and they are all optional, so I have no way of knowing which ones will appear first in the DOM. That's why I was hoping for a way to get the panels from the accordion component directly. Guess that's not possible. Thanks for the input!
  • Aaron Hazelton
    Aaron Hazelton over 5 years
    Thanks for the input, see comment above.
  • Kalamarico
    Kalamarico over 5 years
    So, you have 1 mat-accordion and inside you have some *ngFor applied to a mat-expansion-panel. Is that right? (1 accordion and inside X mat-expansion-panels)
  • Kalamarico
    Kalamarico over 5 years
    If I'm right, have you consider to have only one mat-expansion-panel with *ngFor and use the object iterated in the ngFor for your purpose? I'm saying, if you are doing "let item in myObject" inside ngFor, you can "customize" myObject with all the panels items, instead of use several panel objects and write more than one ngFor.... Maybe you can't do that, if you can add a stackblitz example could be better to help
  • Aaron Hazelton
    Aaron Hazelton over 5 years
    Its a pretty complex config object and everything on page is getting built from it. Reason I'm doing that is that the configs can differ greatly, so I'm using ng-containers to see if a certain property of the object exists and if so, then using another container to project my template with an ngFor. Since each of these (all optional) objects are all handled differently, there are multiple templates, too. I could add another ngFor as the parent to all of this stuff, but it would be another layer of complexity that would be unnecessary. Not a big deal, will add it if they really want it.
  • Kalamarico
    Kalamarico over 5 years
    I understand, another choice I'm thinking is, you can create a custom directive, and use it in the mat-expansion-panel with ngFor. In that directive you can use a static counter and set a ++ the counter when it's rendered, so, the expanded attr will set to true when that counter is the first... If I can I will show an example
  • Aaron Hazelton
    Aaron Hazelton over 5 years
    Good idea. I'll see how 'must have' this is first. Thanks!
  • Kalamarico
    Kalamarico over 5 years
    You can use a static class for create inside the counter, and import it in the directive (and it will use it to sum) and import also in the component (for use it in the template) I hope solve your problem, if you have problems, comment again! ;)