Home > database >  Angular | How to open one accordion at a time with NgFor?
Angular | How to open one accordion at a time with NgFor?

Time:01-05

How do I make one accordion open at a time with an ngFor in the code?

I would like to try inserting an If which indicates that if one accordion is open, the other closes automatically. If I try to put the ngIf in the html, the accordion no longer works and is not shown. What am I doing wrong?

user-detail.component.ts

    <mat-accordion >
    <mat-expansion-panel 
    (click)="commentOpen(post.id)">
      <mat-expansion-panel-header *ngIf="panelOpenState">
        <mat-panel-title>
          Self aware panel
        </mat-panel-title>
        <mat-panel-description>
          Currently I am {{panelOpenState ? 'open' : 'closed'}}
        </mat-panel-description>
      </mat-expansion-panel-header>
      <form [formGroup]="commentForm" >
        <input matInput type="text" formControlName="email" placeholder="email" #commentEmail required>
        <input matInput type="text" formControlName="name" #commentName placeholder="name" required>
        <textarea matInput  formControlName="body" #commentBody placeholder="Commenta..."></textarea>
        <button type="submit" [disabled]="commentForm.invalid" 
        (click)="onSubmitComment(commentEmail.value, commentName.value, commentBody.value, post.id)">Invia</button>
      </form>

      <div id="txtdataCommens" *ngFor="let comment of comments">
        {{comment.id}}
        <br>
        {{comment.email}}
        <br>
        {{comment.name}}
        <br>
        {{comment.body}}
      </div>
    </mat-expansion-panel>
  </mat-accordion>

user-detail.component.ts

panelOpenState = false;

commentOpen(idPost:any){
    this.commentService.postId = idPost
    this.getCommentDetailByUser();
    this.panelOpenState = !this.panelOpenState
  }

CodePudding user response:

Use the expanded directive to collapse/expand the corresponding panel and keep track of the opened panel index in your component, e.g.

Template:

<mat-accordion >
  <mat-expansion-panel
    *ngFor="let entry of data; let i = index"
    [expanded]="step === i"
    (opened)="setStep(i)"
    hideToggle
  >
    <mat-expansion-panel-header>
      <mat-panel-title> {{entry.name}} </mat-panel-title>
    </mat-expansion-panel-header>
    <div>
      Some panel content
    </div>
  </mat-expansion-panel>
</mat-accordion>

Component:

@Component({
  selector: "app-root",
  templateUrl: "./app.component.html",
  styleUrls: ["./app.component.scss"]
})
export class AppComponent {
  step = 0;
  data = [{ name: "test" }, { name: "test2" }];

  setStep(index: number) {
    this.step = index;
  }
}

Codesandbox example: https://codesandbox.io/embed/angular-material-forked-0yfiye?fontsize=14&hidenavigation=1&theme=dark

CodePudding user response:

use below code snippet wich will work with *ngFor to open one accordion at a time. Here we are using 'expanded' directive with index from ngFor which will set step to open

<mat-accordion >
            <mat-expansion-panel [expanded]="step === i" (opened)="setStep(i)" hideToggle *ngFor="let comment of comments; let i = index"
            (click)="commentOpen(post.id)">
              <mat-expansion-panel-header>
                <mat-panel-title>
                  Self aware panel {{i}}
                </mat-panel-title>
                <mat-panel-description>
                  Currently I am
                </mat-panel-description>
              </mat-expansion-panel-header>
              <!-- <form [formGroup]="commentForm" >
                <input matInput type="text" formControlName="email" placeholder="email" #commentEmail required>
                <input matInput type="text" formControlName="name" #commentName placeholder="name" required>
                <textarea matInput  formControlName="body" #commentBody placeholder="Commenta..."></textarea>
                <button type="submit" [disabled]="commentForm.invalid" 
                (click)="onSubmitComment(commentEmail.value, commentName.value, commentBody.value, post.id)">Invia</button>
              </form> -->
              sample form
        
              <div id="txtdataCommens">
                {{comment.id}}
                <br>
                {{comment.email}}
                <br>
                {{comment.name}}
                <br>
                {{comment.body}}
              </div>
            </mat-expansion-panel>
          </mat-accordion>

In .TS you need to declare steps variable like given below

step:number = 0;

And add below method in the same .ts file

setStep(index)
{
  this.step = index;
}
  • Related