Angular mat-table colspan 不会跳过列,在表中留下额外的列

问题描述 投票:0回答:1

在我的 12 个月的 mat-table 中,我尝试跨多个月跨单元格。但是,数据源中不会跳过跨越的月份,因此在表末尾添加了额外的列。例如:我在 3 月启动一个单元格,colspan = 2,但现在 4 月数据被放置在 5 月列中,5 月数据被放置在 6 月列中,依此类推。

Table with extra columns

----- html -----

<table mat-table [dataSource]="dataSource" multiTemplateDataRows class="mat-elevation-z8">
        @for (column of columnsToDisplay; track column) {
            <ng-container matColumnDef="{{column}}">
            <th mat-header-cell *matHeaderCellDef> {{ column }}</th>
            <td mat-cell *matCellDef="let element" [attr.colspan]="element[column].colspan" [style.background-color]="element[column].color">{{ element[column].name }}</td>
            </ng-container>
        }

        <ng-container matColumnDef="expand">
            <th mat-header-cell *matHeaderCellDef aria-label="row actions">&nbsp;</th>
            <td mat-cell *matCellDef="let element">
            <button mat-icon-button aria-label="expand row" (click)="(expandedElement = expandedElement === element ? null : element); $event.stopPropagation()">
                @if (expandedElement === element) {
                <mat-icon>keyboard_arrow_up</mat-icon>
                } @else {
                <mat-icon>keyboard_arrow_down</mat-icon>
                }
            </button>
            </td>
        </ng-container>

        <!-- Expanded Content Column - The detail row is made up of this one column that spans across all columns -->
        <ng-container matColumnDef="expandedDetail">
            <td mat-cell *matCellDef="let element" [attr.colspan]="columnsToDisplayWithExpand.length">
            <div class="example-element-detail" [@detailExpand]="element == expandedElement ? 'expanded' : 'collapsed'">
                <div class="example-element-description">
                {{element.description}}
                <span class="example-element-description-attribution"></span>
                </div>
            </div>
            </td>
        </ng-container>

        <tr mat-header-row *matHeaderRowDef="columnsToDisplayWithExpand"></tr>
        <tr mat-row *matRowDef="let element; columns: columnsToDisplayWithExpand;"
            class="example-element-row"
            [class.example-expanded-row]="expandedElement === element"
            (click)="expandedElement = expandedElement === element ? null : element">
        </tr>
        <tr mat-row *matRowDef="let row; columns: ['expandedDetail']" class="example-detail-row"></tr>
    </table>

----- TypeScript -----

import { Component } from '@angular/core';
import { animate, state, style, transition, trigger } from '@angular/animations';
import { MatTableDataSource } from '@angular/material/table';

@Component({
  selector: 'app-fertilization',
  templateUrl: './fertilization.component.html',
  styleUrl: './fertilization.component.scss',
  animations: [
    trigger('detailExpand', [
      state('collapsed,void', style({ height: '0px', minHeight: '0' })),
      state('expanded', style({ height: '*' })),
      transition(
        'expanded <=> collapsed',
        animate('225ms cubic-bezier(0.4, 0.0, 0.2, 1)')
      ),
    ]),
  ],
})
export class FertilizationComponent {
  public dataSource: any = new MatTableDataSource();
  public fertilizationSchedule: YearElement[] = [];
  columnsToDisplay = [
    'Jan',
    'Feb',
    'Mar',
    'Apr',
    'May',
    'June',
    'July',
    'Aug',
    'Sept',
    'Oct',
    'Nov',
    'Dec',
  ];
  columnsToDisplayWithExpand = [...this.columnsToDisplay, 'expand'];
  expandedElement: YearElement | undefined;

  constructor() {
    this.fertilizationSchedule = [
      { Jan: new Element(), Feb: new Element(), Mar: {name: "Step 1 - Early Spring", colspan: 2, color: "#ffff91"}, Apr: new Element(), May: new Element(), June: new Element(), July: new Element(), Aug: new Element(), Sept: new Element(), Oct: new Element(), Nov: new Element(), Dec: new Element(), description: "Fertilizer for lawn + pre-emergent weed control" }
    ];

    this.dataSource = this.fertilizationSchedule;
  }
}

interface YearElement {
  Jan?: Element;
  Feb?: Element;
  Mar?: Element;
  Apr?: Element;
  May?: Element;
  June?: Element;
  July?: Element;
  Aug?: Element;
  Sept?: Element;
  Oct?: Element;
  Nov?: Element;
  Dec?: Element;
  description: string; // Expanded Item
}

class Element {
  name: string = "";
  colspan?: number;
  color?: string;
}

-----CSS-----

table {
            width: 100%;
        }
        
        tr.example-detail-row {
            height: 0;
        }
        
        tr.example-element-row:not(.example-expanded-row):hover {
            background: whitesmoke;
        }
        
        tr.example-element-row:not(.example-expanded-row):active {
            background: #efefef;
        }
        
        .example-element-row td {
            border-bottom-width: 0;
        }
        
        .example-element-detail {
            overflow: hidden;
            display: flex;
        }
        
        .example-element-diagram {
            min-width: 80px;
            border: 2px solid black;
            padding: 8px;
            font-weight: lighter;
            margin: 8px 0;
            height: 104px;
        }
        
        .example-element-symbol {
            font-weight: bold;
            font-size: 40px;
            line-height: normal;
        }
        
        .example-element-description {
            padding: 16px;
        }
        
        .example-element-description-attribution {
            opacity: 0.5;
        }

我的表格由 12 列组成,每列代表一个月。我希望一些细胞能够在几个月内跨越。我尝试将列设为可选,希望跳过这些月份,因为无论如何我的 colspan 都在他们的列中。然而,它们只是被推到一列上,导致行末尾出现额外的列。

css angular angular-material datasource angular-material-table
1个回答
0
投票

当您使用 colspan 时,您应该“删除”右侧标记 colspan 的许多列。因此,无论如何,您都应该将此列标记为不显示。

为此,您需要转换您的数组。这个想法是,例如你有

this.fertilizationSchedule = [
  { Jan: new Element(), 
    Feb: new Element(), 
    Mar: {name: "Step 1 - Early Spring", colspan: 2, color: "#ffff91"},
    Apr: new Element(), 
    May: new Element(), 
    June: {name: "Step 1 - Early Spring", colspan: 3, color: "#ffff91"}, 
    July:new Element(), 
    Aug:new Element(), 
    Sept:new Element(), 
    Oct:new Element(), 
    ...
  }

转型之路

this.fertilizationSchedule = [
  { Jan: new Element(), 
    Feb: new Element(), 
    Mar: {name: "Step 1 - Early Spring", colspan: 2, color: "#ffff91"},
    Apr: {colspan:-1}, //<--this colspan=-1
    May: new Element(), 
    June:new Element(), 
    June:{name: "Step 1 - Early Spring", colspan: 3, color: "#ffff91"}, 
    July:{colspan:-1},  //<--this colspan=-1 
    Aug: {colspan:-1},   //<--this colspan=-1
    Sept:new Element(), 
    Oct:new Element(), 
    ...
  }
]

所以你可以写一些类似的东西

@for (column of columnsToDisplay; track column) {
   <ng-container matColumnDef="{{column}}">
     <th mat-header-cell *matHeaderCellDef> {{ column }}</th>
     @if (element[column].colspan!=-1) //if "colspan=-1" NOT create
     {
       <td mat-cell *matCellDef="let element" 
           [attr.colspan]="element[column].colspan" 
           [style.background-color]="element[column].color">
           {{ element[column].name }}
       </td>
     }
   </ng-container>
 }

怎么做呢?创建一个函数:

fertilizationFormatted(fertilizationSchedule:any[])
{
  const fer=fertilizationSchedule.map((element:any)=>{ //with each row

    this.columnsToDisplay.forEach((col:string,index:number)=>{ //with each column
          if (element[col]?.colspan>1)
          {
             let i=1;
             while (index+i<12 && i<element[col].colspan){
                element[this.columnsToDisplay[index+i]]={colspan:-1}
                i++;
             }
          }
    })
    return element;
 })
 return fer;
}

this.dataSource = this.fertilizationFormatted(this.fertilizationSchedule);
© www.soinside.com 2019 - 2024. All rights reserved.