无模型的角度材质表动态列

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

我需要使用没有模型的角材料表,因为我不知道服务会带来什么。

所以我在组件中动态初始化我的

MatTableDataSource
displayedColumns
:

表格组件:

ngOnInit() {

this.vzfPuanTablo = [] //TABLE DATASOURCE

//GET SOMETHING FROM SERVICE 
this.listecidenKisi = this.listeciServis.listecidenKisi;
this.listecidenVazife = this.listeciServis.listecidenVazife;

//FILL TABLE DATASOURCE 
var obj = {};
for (let i in this.listecidenKisi ){
    for( let v of this.listecidenVazife[i].vazifeSonuclar){
        obj[v.name] = v.value;
    }
    this.vzfPuanTablo.push(obj);
    obj={};
}

//CREATE DISPLAYED COLUMNS DYNAMICALLY
this.displayedColumns = [];
for( let v in this.vzfPuanTablo[0]){
    this.displayedColumns.push(v);
}

//INITIALIZE MatTableDataSource
this.dataSource = new MatTableDataSource(this.vzfPuanTablo);
}

代码最重要的部分在这里:

for( let v in this.vzfPuanTablo[0]) {
   this.displayedColumns.push(v);
}

我在这里动态创建

displayedColumns
,这意味着;即使我不知道服务会带来什么,我也可以在表格中显示出来。

例如

displayedColumns
可以是这样的:

  • [“一”、“二”、“三”、“四”、“五”]

  • [“堆栈”,“溢出”,“帮助”,“我]

但这不是问题,因为我可以处理。


但是当我想用HTML显示它时,我无法正确显示,因为

matCellDef
事情:

表格Html:

    <mat-table #table [dataSource]="dataSource" class="mat-elevation-z8">

        <ng-container *ngFor="let disCol of displayedColumns; let colIndex = index" matColumnDef="{{disCol}}">
            <mat-header-cell *matHeaderCellDef>{{disCol}}</mat-header-cell>
            <mat-cell *matCellDef="let element "> {{element.disCol}}
            </mat-cell>
        </ng-container>

        <mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
        <mat-row *matRowDef="let row; columns: displayedColumns;"></mat-row>
    </mat-table>

我的问题在这里:

<mat-cell *matCellDef="let element "> {{element.disCol}} < / mat-cell>

其实我想在单元格中显示

element."disCol's value"
,但我不知道该怎么做。

否则,除了这个

element."disCol's value"
事情,一切都好。


当我使用

{{element.disCol}}
显示
value of element that has disCols's value
时,所有单元格都是空的:

仅使用

{{element}}
的其他示例:


也如您所见:

  1. 表数据源是动态变化的。这意味着我无法轻松使用

    {{element.ColumnName}}
    ,因为我什至不知道它是什么。

    • 第一个示例的 displayedColumns = ['Vazife', 'AdSoyad', 'Kirmizi', 'Mavi', 'Yesil', 'Sari'];
    • 第二个示例的 displayedColumns = ['Muhasebe', 'Ders', 'Egitim', 'Harici'];
  2. matHeaderCellDef
    是正确的,因为它直接使用{{disCol}}。

但是我需要读取disCol的值,并在单元格中显示

element.(disCol's value)

我该怎么做?

dynamic interface angular-material datasource
4个回答
80
投票

我找到了解决方案:) 这非常非常简单,但我一开始看不到:) 就这样:

        <mat-cell *matCellDef="let element "> {{element[disCol]}}
        </mat-cell>

我必须仅在 HTML 中使用

{{element[disCol]}}

现在,一切都好:)


17
投票

查看基于@mevaka 的完整工作示例

其中

jobDetails$
是项目数组。

columns$
相当于
Object.keys(jobDetails$[0])
所以只是
string[]

<table mat-table [dataSource]="jobDetails$ | async">
  
  <ng-container *ngFor="let disCol of (columns$ | async); let colIndex = index" matColumnDef="{{disCol}}">
    <th mat-header-cell *matHeaderCellDef>{{disCol}}</th>
    <td mat-cell *matCellDef="let element">{{element[colIndex]}}</td>
  </ng-container>


  <tr mat-header-row *matHeaderRowDef="(columns$ | async)"></tr>
  <tr mat-row *matRowDef="let row; columns: (columns$ | async)"></tr>
</table>

12
投票

我已尽力将动态表简化到最低限度。此示例将显示给定具有任意键的平面对象数组的任意列。请注意第一个对象如何具有额外的“foo”属性,该属性会导致创建整个列。 DATA const 可能是您从服务获取的一些数据。另外,如果您知道一些将获得 JSON 的常见属性名称,您可以添加“列 ID -> 标签”映射到此。请参阅 stachblitz 此处

import {Component, ViewChild, OnInit} from '@angular/core';

const DATA: any[] = [
  {position: 1, name: 'sdd', weight: 1.0079, symbol: 'H', foo: 'bar'},
  {position: 2, name: 'Helium', weight: 4.0026, symbol: 'He'},
  {position: 3, name: 'Lithium', weight: 6.941, symbol: 'Li'},
  {position: 4, name: 'Beryllium', weight: 9.0122, symbol: 'Be'},
  {position: 5, name: 'Boron', weight: 10.811, symbol: 'B'},
  {position: 6, name: 'Carbon', weight: 12.0107, symbol: 'C'}
];

@Component({
  selector: 'dynamic-table-example',
  styleUrls: ['dynamic-table-example.css'],
  templateUrl: 'dynamic-table-example.html',
})
export class DynamicTableExample implements OnInit {

  columns:Array<any>
  displayedColumns:Array<any>
  dataSource:any
  
  ngOnInit() {
    // Get list of columns by gathering unique keys of objects found in DATA.
    const columns = DATA
      .reduce((columns, row) => {
        return [...columns, ...Object.keys(row)]
      }, [])
      .reduce((columns, column) => {
        return columns.includes(column)
          ? columns
          : [...columns, column]
      }, [])
    // Describe the columns for <mat-table>.
    this.columns = columns.map(column => {
      return { 
        columnDef: column,
        header: column,
        cell: (element: any) => `${element[column] ? element[column] : ``}`     
      }
    })
    this.displayedColumns = this.columns.map(c => c.columnDef);
    // Set the dataSource for <mat-table>.
    this.dataSource = DATA
  }
 
}
<mat-table #table [dataSource]="dataSource">
  <ng-container *ngFor="let column of columns" [cdkColumnDef]="column.columnDef">
    <mat-header-cell *cdkHeaderCellDef>{{ column.header }}</mat-header-cell>
    <mat-cell *cdkCellDef="let row">{{ column.cell(row) }}</mat-cell>
  </ng-container>
  <mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
  <mat-row *matRowDef="let row; columns: displayedColumns;"></mat-row>
</mat-table>


0
投票

从源动态渲染数据表(输入类型='checkbox')

我需要动态渲染列,我还希望将单元格值渲染为复选框。我的代码是从带有过滤的Angular示例表编辑的,并从@Jack获得了动态渲染部分。希望下面附上的代码可以为像我这样的初学者提供一个简单的想法。

我所做的是

  1. <td mat-cell... </td>
     包裹 
    <div *ngIf="condition"></div>
<div *ngIf="disCol === 'username'">
    <td mat-cell *matCellDef="let element"> {{element[disCol]}}</td>
</div>
<div *ngIf="disCol !== 'username'">
    <td mat-cell *matCellDef="let element">
        <input *ngIf="element[disCol] == 'Yes'" type="checkbox" />
        <input *ngIf="element[disCol] == 'No'" type="checkbox" checked/>
    </td>
</div>
  1. 还值得一提的是,我使用的是 Angular 16,导入语句与旧版本略有不同。旧版本基本上直接从
    '@angular/material'
  2. 导入
import { MatButtonModule } from '@angular/material/button';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatInputModule } from '@angular/material/input';
import { MatRippleModule } from '@angular/material/core';
import { MatTableModule } from '@angular/material/table';

动态-tb.component.html

<div class="example-container mat-elevation-z8">

  <mat-table #table [dataSource]="dataSource">
    <ng-container *ngFor="let disCol of displayedColumns; let colIndex = index" matColumnDef="{{disCol}}">
      <th mat-header-cell *matHeaderCellDef>{{disCol}}</th>
      <div *ngIf="disCol === 'username'">
        <td mat-cell *matCellDef="let element"> {{element[disCol] == undefined ? "-NA-" : element[disCol]}}</td>
      </div>
      <div *ngIf="disCol !== 'username'">
        <td mat-cell *matCellDef="let element">
          <input *ngIf="element[disCol] == 'Yes'" type="checkbox" />
          <input *ngIf="element[disCol] == 'No'" type="checkbox" checked/>
        </td>
      </div>
    </ng-container>"

    <mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
    <mat-row *matRowDef="let row; columns: displayedColumns;"></mat-row>
  </mat-table>
</div>

动态-tb.component.ts

import { Component, OnInit } from '@angular/core';
import { MatTableDataSource } from '@angular/material/table';

@Component({
  selector: 'app-dynamic-tb',
  templateUrl: './dynamic-tb.component.html',
  styleUrls: ['./dynamic-tb.component.css']
})
export class DynamicTbComponent implements OnInit {

  displayedColumns: string[] = [];
  dataSource: any;
  ELEMENT_DATA: any[] | undefined;

  ngOnInit(): void {
    this.displayedColumns = ['username', 'feature_1', 'feature_2', 'feature_3'];
    this.ELEMENT_DATA = [
      { username: "Jonah", feature_1: 'Yes', feature_2: 'No', feature_3: 'No' },
      { username: "Alan", feature_1: 'Yes', feature_2: 'No', feature_3: 'Yes' },
      { username: "John", feature_1: 'No', feature_2: 'Yes', feature_3: 'No' },
      { username: "Ann", feature_1: 'Yes', feature_2: 'No', feature_3: 'Yes' },
      { username: "Lee", feature_1: 'No', feature_2: 'No', feature_3: 'No' },
      { username: "Royce", feature_1: 'Yes', feature_2: 'Yes', feature_3: 'No' },
      { username: "Suzzy", feature_1: 'No', feature_2: 'No', feature_3: 'No' },
    ];
    this.dataSource = new MatTableDataSource(this.ELEMENT_DATA);
  }

}

动态-tb.module.ts

import { NgModule } from '@angular/core';

import { DynamicTbComponent } from './profiles.component';
import { CommonModule } from '@angular/common';

import { MatButtonModule } from '@angular/material/button';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatInputModule } from '@angular/material/input';
import { MatRippleModule } from '@angular/material/core';
import { MatTableModule } from '@angular/material/table';

@
NgModule
({
  declarations: [
    DynamicTbComponent
  ],
  imports: [
    CommonModule,
    MatButtonModule,
    MatFormFieldModule,
    MatInputModule,
    MatRippleModule,
    MatTableModule,
  ],
  exports: [
    DynamicTbComponent
  ]
})

export class DynamicTbModule {}

动态-tb.component.css

/* Structure */
.example-container {
  display: flex;
  flex-direction: column;
  min-width: 300px;
}

.example-header {
  min-height: 64px;
  padding: 8px 24px 0;
}

.mat-form-field {
  font-size: 14px;
  width: 100%;
}

.mat-table {
  overflow: auto;
  max-height: 500px;
}

/**
  Added by me
*/
th, td {
  width: 100px;
}
© www.soinside.com 2019 - 2024. All rights reserved.