You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于Angular 4与Angular Material实现动态数据可展开表格行(API获取数据)

Angular 4 + Angular Material: Dynamic Expandable Table Rows with API Data

Got it, let's walk through building an expandable table with dynamic, API-fetched data in Angular 4 using Angular Material. I've tackled this exact scenario before, so here's a practical, step-by-step solution that works:

1. First, Set Up Dependencies

Angular 4 pairs with Angular Material 2.x (beta versions), so make sure you install the right packages:

npm install @angular/material@2.0.0-beta.12 @angular/cdk@2.0.0-beta.12 --save
npm install @angular/animations@4.4.7 --save

Then, import the required modules in your app.module.ts (or a shared module):

import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { MatTableModule, MatExpansionModule, MatProgressSpinnerModule } from '@angular/material';
import { HttpClientModule } from '@angular/common/http';

@NgModule({
  imports: [
    // ... other imports
    BrowserAnimationsModule,
    HttpClientModule,
    MatTableModule,
    MatExpansionModule,
    MatProgressSpinnerModule
  ]
})
export class AppModule { }

2. Component Template (HTML)

We'll create a table where clicking a main row toggles an expanded section with additional details. Since data is dynamic, we'll bind columns dynamically too.

<div class="table-container" *ngIf="!isLoading; else loading">
  <mat-table [dataSource]="dataSource">
    <!-- Dynamic Columns -->
    <ng-container *ngFor="let column of displayedColumns" [matColumnDef]="column">
      <mat-header-cell *matHeaderCellDef> {{ column | titlecase }} </mat-header-cell>
      <mat-cell *matCellDef="let element"> {{ element[column] }} </mat-cell>
    </ng-container>

    <!-- Expandable Row Column -->
    <ng-container matColumnDef="expandedDetail">
      <mat-cell *matCellDef="let element" [attr.colspan]="displayedColumns.length">
        <div class="expanded-content" *ngIf="expandedElement === element">
          <!-- Customize this section with your dynamic detail data -->
          <h4>Details</h4>
          <pre>{{ element.details | json }}</pre>
        </div>
      </mat-cell>
    </ng-container>

    <!-- Main Row -->
    <mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
    <mat-row *matRowDef="let row; columns: displayedColumns;" 
             class="clickable-row"
             (click)="expandedElement = expandedElement === row ? null : row"></mat-row>

    <!-- Expandable Row -->
    <mat-row *matRowDef="let row; columns: ['expandedDetail']" class="expanded-row"></mat-row>
  </mat-table>
</div>

<ng-template #loading>
  <div class="loading-spinner">
    <mat-spinner diameter="50"></mat-spinner>
  </div>
</ng-template>

3. Component Logic (TypeScript)

We'll fetch data from an API, handle dynamic columns, and manage the expanded row state.

import { Component, OnInit } from '@angular/core';
import { HttpClient } from '@angular/common/http';

// Define an interface for your API data (adjust based on your actual response)
interface Record {
  id: number;
  name: string;
  // Add other dynamic fields as needed
  details: { [key: string]: any }; // For the expandable detail content
}

@Component({
  selector: 'app-expandable-table',
  templateUrl: './expandable-table.component.html',
  styleUrls: ['./expandable-table.component.css']
})
export class ExpandableTableComponent implements OnInit {
  dataSource: Record[] = [];
  displayedColumns: string[] = [];
  expandedElement: Record | null = null;
  isLoading = true;

  constructor(private http: HttpClient) { }

  ngOnInit(): void {
    this.fetchDataFromAPI();
  }

  fetchDataFromAPI(): void {
    // Replace with your actual API endpoint
    this.http.get<Record[]>('https://your-api-endpoint.com/data')
      .subscribe({
        next: (data) => {
          this.dataSource = data;
          // Extract dynamic column names (exclude 'details' since it's for expansion)
          if (data.length > 0) {
            this.displayedColumns = Object.keys(data[0]).filter(key => key !== 'details');
          }
          this.isLoading = false;
        },
        error: (err) => {
          console.error('Failed to fetch data:', err);
          this.isLoading = false;
        }
      });
  }
}

4. Add Some Basic Styling (CSS)

Make the table look clean and the expandable section distinguishable:

.table-container {
  margin: 20px;
  overflow-x: auto;
}

.clickable-row {
  cursor: pointer;
}

.clickable-row:hover {
  background-color: #f5f5f5;
}

.expanded-row {
  background-color: #fafafa;
}

.expanded-content {
  padding: 16px;
  border-top: 1px solid #eee;
}

.loading-spinner {
  display: flex;
  justify-content: center;
  margin: 40px;
}

Key Notes for Dynamic Data

  • Dynamic Columns: We extract column names from the first data object using Object.keys()—this works if all your records have the same structure (which they usually do from APIs).
  • Expandable Content: The details field in the Record interface holds the data you want to show when expanding a row. Adjust this to match your API's response structure.
  • State Management: The expandedElement variable tracks which row is currently expanded—clicking the same row collapses it.

This setup will fetch your data dynamically, render a table with expandable rows, and handle loading states gracefully. Let me know if you need to tweak any part for your specific API response!

内容的提问来源于stack exchange,提问作者raghu babu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.11 08:56:37