Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/angular/27.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Html 角度材质表添加动态列标题_Html_Angular_Typescript_Angular Material - Fatal编程技术网

Html 角度材质表添加动态列标题

Html 角度材质表添加动态列标题,html,angular,typescript,angular-material,Html,Angular,Typescript,Angular Material,我目前正在Angular项目中使用一个包,其中包含我为该项目开发的可重用组件。如何使材质表上的列标题/行成为动态的,以便在使用Angular项目中的表时可以将它们作为输入数组传递 其中一些标题是堆叠的或具有唯一的HTML/CSS,这就是我遇到的问题。我尝试在我的组件中创建一个数组,该数组有一个布尔标志,指示列标题/行是否应该包含两个相互堆叠的字段 下面是我当前HTML的一个片段,它不是动态的。您可以看到这两个ng容器是不同的。当我在我的项目中使用我的表时,我怎么能简单地将一个列/行数组作为输入来

我目前正在Angular项目中使用一个包,其中包含我为该项目开发的可重用组件。如何使材质表上的列标题/行成为动态的,以便在使用Angular项目中的表时可以将它们作为输入数组传递

其中一些标题是堆叠的或具有唯一的HTML/CSS,这就是我遇到的问题。我尝试在我的组件中创建一个数组,该数组有一个布尔标志,指示列标题/行是否应该包含两个相互堆叠的字段

下面是我当前HTML的一个片段,它不是动态的。您可以看到这两个ng容器是不同的。当我在我的项目中使用我的表时,我怎么能简单地将一个列/行数组作为输入来传递呢

<ng-container matColumnDef="from">
    <th mat-header-cell *matHeaderCellDef>
      <div [ngStyle] = "{'color': pickupHeader}"  class = "stackedColumn">
        <span (click)="toggleDates($event)">{{ 'shipperFrom' }}</span>
      </div>
      <div [ngStyle] = "{'color': deliveryHeader}" class = "stackedColumn">
        <span (click) = "toggleDates($event)">{{ 'shipperTo' }}</span>
      </div>
    </th>
    <td mat-cell *matCellDef="let element">
      <div>
        <span class = "location"> <img src="{{ element.Flag }}">{{element.PickupCity}}</span>
      </div>
      <div>
        <span class = "location"><img src="{{ element.Flag }}">{{element.DeliveryCity}}</span>
      </div>
    </td>
  </ng-container>

  <ng-container matColumnDef="legs">
    <th mat-header-cell *matHeaderCellDef> {{ somethingElse }} </th>
    <td mat-cell *matCellDef="let element"> {{element.SomethingElse}} </td>
  </ng-container>
我想让对象数组填充表格,知道它应该使用哪种HTML,这样当我在项目中导入和使用它时,我就只需要这些了:

<the-table [dataSource] = "data"></the-table>


基本上,我希望能够动态地向表中添加列/行,而不必返回并编辑包。

我也做了类似的事情。请记住,我在下面做了一点修改,去掉了一些特定于项目的细节,所以如果有问题,请告诉我

component.html:

<mat-table matSort [dataSource]="dataSource">
    <ng-container *ngFor="let column of displayedColumns; index as i" [matColumnDef]="column">
        <mat-header-cell *matHeaderCellDef class="col-search" fxLayoutAlign="start start" fxLayout="column">
            <span mat-sort-header>{{ getColumnLabel(column) }}</span>
            <!--The below is incomplete Just remove if you don't need filtering--> 
            <input
                matInput
                autocomplete="off"
                id="{{ column + i }}"
                (keyup)="myCustomFilterCode()" 
                placeholder="Filter"
            />
        </mat-header-cell>
        <mat-cell *matCellDef="let row">{{ row[column] }}</mat-cell>
    </ng-container>
    <!--This ngStyle is specifically for fixedWidth tables which are meant to be horizontally scrollable-->
    <mat-header-row [ngStyle]="{ 'min-width.px': width ? width : null }" *matHeaderRowDef="displayedColumns"></mat-header-row>
    <mat-row [ngStyle]="{ 'min-width.px': width ? width : null }" *matRowDef="let row; columns: displayedColumns"> </mat-row>
</mat-table>
<mat-paginator [pageSizeOptions]="pageSizeOptions" showFirstLastButtons [pageSize]="startingPageSize"></mat-paginator>

{{getColumnLabel(column)}
{{行[列]}}
组件技术


/**This component will dynamically create a mat-table for a set of data */
@Component({
    selector: 'dynamic-mat-table',
    templateUrl: './dynamic-mat-table.component.html',
    styleUrls: ['./dynamic-mat-table.component.scss'],
    providers: [DatePipe]
})
export class DynamicMatTableComponent implements OnInit, OnChanges {
    /**The data to generate a table for */
    @Input()
    tableData: Object[];

    /** This will override the column names in the table, the id will be the property name (i.e. propertyID)
     * and the value will be the column header text 
     *
     *  **This is Only Necessary if you don't like the Automatically created column names**
     */
    @Input()
    columnLabels: IdValuePair[];

    /**List of column property names (i.e. propertyID) to ignore */
    @Input()
    ignoreColumns: string[];

    /**Sets the starting page size for the paginator */
    @Input()
    startingPageSize: number;

    /**Sets the page size options for the paginator */
    @Input()
    pageSizeOptions: number[];

    /**Defaults to false, when true the table will be generated with a width of # of columns * columnWidth,
     * otherwise column widths will not be specified (will fill container with equal width columns) */
    @Input()
    fixedWidth = false;

    /**Defaults to 250, Only used when fixedWidth = true if not set this determines the width of each column */
    @Input()
    columnWidth = 250;

    width: number;
    dataSource = new MatTableDataSource<Object>();
    fullColumnLabels: IdValuePair[] = [];
    displayedColumns: string[];
    @ViewChild(MatPaginator, { static: true })
    paginator: MatPaginator;
    @ViewChild(MatSort, { static: true })
    sort: MatSort;

    constructor(private datePipe: DatePipe) {}

    ngOnInit() {}

    /**Generate dynamic table whenever inputs change */
    ngOnChanges() {
        this.initTable();
        if (this.tableData && this.tableData.length > 0) {
            this.displayedColumns = Object.keys(this.tableData[0]);
            this.removeIgnoredColumns();
            this.createLabelsForColumns(this.displayedColumns);
            this.calculateRowWidth(this.displayedColumns.length);
            this.dataSource.data = this.pipeData([...this.tableData]);
        }
    }

    /**Create the labels array for each column */
    private createLabelsForColumns(columns: string[]) {
        this.fullColumnLabels = this.columnLabels;
        if (this.fullColumnLabels === undefined) {
            this.fullColumnLabels = [];
        }
        if (this.tableData && this.tableData.length > 0) {
            columns.forEach(x => {
                if (!this.fullColumnLabels.some(label => label.id === x)) {
                    this.fullColumnLabels.push(new IdValuePair(x, _.startCase(x)));
                }
            });
        }
    }

    /**Remove ignored columns to prevent from being displayed */
    private removeIgnoredColumns() {
        if (this.ignoreColumns) {
            this.displayedColumns = this.displayedColumns.filter(x => !this.ignoreColumns.some(y => y === x));
        }
    }

    /**Calculate the row width by the number of columns */
    private calculateRowWidth(columnNumber: number) {
        if (this.fixedWidth) {
            this.width = columnNumber * this.columnWidth;
        }
    }

    /**Initialize table */
    private initTable() {
        this.dataSource.paginator = this.paginator;

        this.dataSource.sort = this.sort;
    }

    /**Cleans up data with pipes if necessary*/
    private pipeData(data: Object[]): Object[] {
        data = this.pipeDates(data);
        return data;
    }

    /**Pipe dates through a date pipe if the property name contains 'date' and the value looks like a date*/
    private pipeDates(data: Object[]): Object[] {
        // ISO_8601 is what .net core returns, may need to expand this list
        const formats = [moment.ISO_8601];
        // Loop through each row of data
        data.forEach((row, index) => {
            // Loop through each property in each row
            Object.keys(data[index]).forEach(propertyName => {
                // Get the value of the property
                const value = data[index][propertyName];

                // If the value matches a format in the format list, then transform it to a short date
                if (propertyName.toLowerCase().search('date') !== -1 && moment(value, formats, true).isValid()) {
                    data[index][propertyName] = this.datePipe.transform(value, 'short');
                }
            });
        });
        return data;
    }

    /**Gets the label for a given column from the property name */
    getColumnLabel(column: string): string {
        return this.fullColumnLabels.find(x => x.id === column).value;
    }
}

/**此组件将为一组数据动态创建mat表*/
@组成部分({
选择器:“动态垫表”,
templateUrl:'./dynamic mat table.component.html',
styleUrls:['./dynamic mat table.component.scss'],
提供者:[日期管道]
})
导出类DynamicAttributeComponent实现OnInit、OnChanges{
/**要为其生成表的数据*/
@输入()
tableData:对象[];
/**这将覆盖表中的列名,id将是属性名(即propertyID)
*并且该值将是列标题文本
*
***仅当您不喜欢自动创建的列名时才需要此选项**
*/
@输入()
columnLabels:IdValuePair[];
/**要忽略的列属性名称(即propertyID)列表*/
@输入()
ignoreColumns:string[];
/**设置分页器的起始页大小*/
@输入()
开始页面大小:数字;
/**设置分页器的页面大小选项*/
@输入()
页面大小选项:编号[];
/**默认为false,如果为true,将生成宽度为#of columns*columnWidth的表,
*否则,将不指定列宽(将用等宽列填充容器)*/
@输入()
fixedWidth=false;
/**默认值为250,仅在fixedWidth=true时使用,如果未设置,则此值确定每列的宽度*/
@输入()
柱宽=250;
宽度:数字;
dataSource=新MatTableDataSource();
fullColumnLabels:IdValuePair[]=[];
displayedColumns:字符串[];
@ViewChild(MatPaginator,{static:true})
paginator:MatPaginator;
@ViewChild(MatSort,{static:true})
排序:MatSort;
构造函数(私有datePipe:datePipe){}
ngOnInit(){}
/**在输入更改时生成动态表*/
ngOnChanges(){
this.initTable();
if(this.tableData&&this.tableData.length>0){
this.displayedColumns=Object.keys(this.tableData[0]);
this.removeIgnoredColumns();
this.createLabelsForColumns(this.displayedColumns);
this.calculateRowWidth(this.displayedColumns.length);
this.dataSource.data=this.pipeData([…this.tableData]);
}
}
/**为每列创建标签数组*/
私有createLabelsForColumns(列:字符串[]){
this.fullColumnLabels=this.columnLabels;
if(this.fullColumnLabels===未定义){
this.fullColumnLabels=[];
}
if(this.tableData&&this.tableData.length>0){
columns.forEach(x=>{
如果(!this.fullColumnLabels.some(label=>label.id==x)){
this.fullColumnLabels.push(新的IdValuePair(x,u.startCase(x));
}
});
}
}
/**删除被忽略的列以防止显示*/
私有removeIgnoredColumns(){
if(this.ignoreColumns){
this.displayedColumns=this.displayedColumns.filter(x=>!this.ignoreColumns.some(y=>y==x));
}
}
/**按列数计算行宽*/
专用计算器wWidth(列号:number){
如果(此.fixedWidth){
this.width=columnNumber*this.columnWidth;
}
}
/**初始化表*/
私有initTable(){
this.dataSource.paginator=this.paginator;
this.dataSource.sort=this.sort;
}
/**如有必要,使用管道清理数据*/
专用管道数据(数据:对象[]):对象[]{
数据=此。管道日期(数据);
返回数据;
}
/**如果属性名称包含“date”且值看起来像日期,则通过日期管道传递日期*/
专用管道日期(数据:对象[]):对象[]{
//ISO_8601是.net core返回的,可能需要扩展此列表
常量格式=[moment.ISO_8601];
//循环遍历每一行数据
data.forEach((行,索引)=>{
//循环遍历每行中的每个属性
Object.keys(数据[索引]).forEach(propertyName=>{
//获取属性的值
常量值=数据[索引][属性名称];
//如果该值与格式列表中的格式匹配,则将其转换为短日期
if(propertyName.toLowerCase().search('date')!=-1&&moment(值、格式、true).isValid()){

/**This component will dynamically create a mat-table for a set of data */
@Component({
    selector: 'dynamic-mat-table',
    templateUrl: './dynamic-mat-table.component.html',
    styleUrls: ['./dynamic-mat-table.component.scss'],
    providers: [DatePipe]
})
export class DynamicMatTableComponent implements OnInit, OnChanges {
    /**The data to generate a table for */
    @Input()
    tableData: Object[];

    /** This will override the column names in the table, the id will be the property name (i.e. propertyID)
     * and the value will be the column header text 
     *
     *  **This is Only Necessary if you don't like the Automatically created column names**
     */
    @Input()
    columnLabels: IdValuePair[];

    /**List of column property names (i.e. propertyID) to ignore */
    @Input()
    ignoreColumns: string[];

    /**Sets the starting page size for the paginator */
    @Input()
    startingPageSize: number;

    /**Sets the page size options for the paginator */
    @Input()
    pageSizeOptions: number[];

    /**Defaults to false, when true the table will be generated with a width of # of columns * columnWidth,
     * otherwise column widths will not be specified (will fill container with equal width columns) */
    @Input()
    fixedWidth = false;

    /**Defaults to 250, Only used when fixedWidth = true if not set this determines the width of each column */
    @Input()
    columnWidth = 250;

    width: number;
    dataSource = new MatTableDataSource<Object>();
    fullColumnLabels: IdValuePair[] = [];
    displayedColumns: string[];
    @ViewChild(MatPaginator, { static: true })
    paginator: MatPaginator;
    @ViewChild(MatSort, { static: true })
    sort: MatSort;

    constructor(private datePipe: DatePipe) {}

    ngOnInit() {}

    /**Generate dynamic table whenever inputs change */
    ngOnChanges() {
        this.initTable();
        if (this.tableData && this.tableData.length > 0) {
            this.displayedColumns = Object.keys(this.tableData[0]);
            this.removeIgnoredColumns();
            this.createLabelsForColumns(this.displayedColumns);
            this.calculateRowWidth(this.displayedColumns.length);
            this.dataSource.data = this.pipeData([...this.tableData]);
        }
    }

    /**Create the labels array for each column */
    private createLabelsForColumns(columns: string[]) {
        this.fullColumnLabels = this.columnLabels;
        if (this.fullColumnLabels === undefined) {
            this.fullColumnLabels = [];
        }
        if (this.tableData && this.tableData.length > 0) {
            columns.forEach(x => {
                if (!this.fullColumnLabels.some(label => label.id === x)) {
                    this.fullColumnLabels.push(new IdValuePair(x, _.startCase(x)));
                }
            });
        }
    }

    /**Remove ignored columns to prevent from being displayed */
    private removeIgnoredColumns() {
        if (this.ignoreColumns) {
            this.displayedColumns = this.displayedColumns.filter(x => !this.ignoreColumns.some(y => y === x));
        }
    }

    /**Calculate the row width by the number of columns */
    private calculateRowWidth(columnNumber: number) {
        if (this.fixedWidth) {
            this.width = columnNumber * this.columnWidth;
        }
    }

    /**Initialize table */
    private initTable() {
        this.dataSource.paginator = this.paginator;

        this.dataSource.sort = this.sort;
    }

    /**Cleans up data with pipes if necessary*/
    private pipeData(data: Object[]): Object[] {
        data = this.pipeDates(data);
        return data;
    }

    /**Pipe dates through a date pipe if the property name contains 'date' and the value looks like a date*/
    private pipeDates(data: Object[]): Object[] {
        // ISO_8601 is what .net core returns, may need to expand this list
        const formats = [moment.ISO_8601];
        // Loop through each row of data
        data.forEach((row, index) => {
            // Loop through each property in each row
            Object.keys(data[index]).forEach(propertyName => {
                // Get the value of the property
                const value = data[index][propertyName];

                // If the value matches a format in the format list, then transform it to a short date
                if (propertyName.toLowerCase().search('date') !== -1 && moment(value, formats, true).isValid()) {
                    data[index][propertyName] = this.datePipe.transform(value, 'short');
                }
            });
        });
        return data;
    }

    /**Gets the label for a given column from the property name */
    getColumnLabel(column: string): string {
        return this.fullColumnLabels.find(x => x.id === column).value;
    }
}