Search code examples
angularmat-card

Nested Mat-Card Angular 12


I'm developing a dashboard where each user can visualize his "workspace" and "projects" (a workspace can have multiple projects). To do that I've created two mat-cards combined with ngFor in this way:

 <mat-card id="ws.id" *ngFor="let ws of workspace; let i = index">        
    <mat-card-header class="app">
        <div class="column1">
            <mat-card-title>WorkSpace: {{ws.name}}
                <button mat-icon-button [matMenuTriggerFor]="menu">
                    <mat-icon>more_vert</mat-icon>
                </button>
                ...
            </mat-card-title>
        </div>
        <div class="column2">
            ...
        </div>
    </mat-card-header>

    <mat-card-content [style.overflow]="'auto'" [style.height.px]="'280'">
        <div class="content" style="width: 95%;">
            <div id="ws.name" fxLayout="row wrap" style="align-self: flex-start;"  fxLayoutGap="16px grid">
                <div id="ws.id" style="align-self: flex-start;" fxFlex="25%" fxFlex.xs="100%" fxFlex.sm="33%" *ngFor="let project of projects; let i = index">
                    <mat-card id="projects" class="mat-elevation-z4" *ngIf="ws.id === project.ws_id">
                        <mat-card-header id="{{project.id}}"  class="app">
                            <div class="column1">                              
                                <mat-card-title>{{project.title}}</mat-card-title>
                            </div>
                            <div class="column2">
                                xxx
                            </div>
                        </mat-card-header>

                        <mat-card-content [routerLink]="['/projects/', project.ws_id, project.id]" style="text-align: center;">
                           ...
                        </mat-card-content>
                    </mat-card>
                </div>
            </div>
        </div>
    </mat-card-content>

</mat-card>

The second workspace card starts with a number of empty project cards equal to the number of projects on the first card. In the attached image I have 7 projects on the first workspace and as can be seen, the projects on the second workspace start from the 8th "position" with 7 empty cards first.

enter image description here

Is there a way to reset the index of the second workspace card? is it the correct approach?


Solution

  • Problem is you're rendering project cards even for the projects you don't want to show. And those cards take up space.

    I'd fix that with wrapping whole card into a ng-container, which is not rendered in the DOM tree as a node, but only renders content it contains. That way you don't end up with empty nodes which take up space.

    Try out something like this:

     <mat-card id="ws.id" *ngFor="let ws of workspace; let i = index">        
        <mat-card-header class="app">
            <div class="column1">
                <mat-card-title>WorkSpace: {{ws.name}}
                    <button mat-icon-button [matMenuTriggerFor]="menu">
                        <mat-icon>more_vert</mat-icon>
                    </button>
                    ...
                </mat-card-title>
            </div>
            <div class="column2">
                ...
            </div>
        </mat-card-header>
    
        <mat-card-content [style.overflow]="'auto'" [style.height.px]="'280'">
            <div class="content" style="width: 95%;">
                <div id="ws.name" fxLayout="row wrap" style="align-self: flex-start;"  fxLayoutGap="16px grid">
                  <ng-container *ngFor="let project of projects; let i = index">
                    <ng-container *ngIf="ws.id === project.ws_id">
                      <div id="ws.id" style="align-self: flex-start;" fxFlex="25%" fxFlex.xs="100%" fxFlex.sm="33%">
                          <mat-card id="projects" class="mat-elevation-z4">
                              <mat-card-header id="{{project.id}}"  class="app">
                                  <div class="column1">                              
                                      <mat-card-title>{{project.title}}</mat-card-title>
                                  </div>
                                  <div class="column2">
                                      xxx
                                  </div>
                              </mat-card-header>
    
                              <mat-card-content [routerLink]="['/projects/', project.ws_id, project.id]" style="text-align: center;">
                                 ...
                              </mat-card-content>
                          </mat-card>
                      </div>
                    </ng-container>
                  </ng-container>
                </div>
            </div>
        </mat-card-content>
    
    </mat-card>