Отображать вложенный объект в столбце в начале
Я следую шаблонной опции, указанной в основных документах, чтобы создать ссылку с данными столбца рядом с основным столбцом данных, но я не могу показать вложенный объект, используя {{data[col.field]}}.
<p-column [field]="col.field" [header]="col.header" [sortable]="col.sortable" [filter]="col.filter" [editable]="col.editable" [filterPlaceholder]="col.filterPlaceholder" styleClass="{{col.class}}">
<ng-template let-col let-data="rowData" let-ri="rowIndex" pTemplate="body">
<span *ngIf="!col.field.includes('.')" >{{data[col.field]}}</span>
<!-- <span *ngIf="col.field.includes('.')">{{data[col.field.split('.')[0]][col.field.split('.')[1]]}}</span> this does not work because field is like x.y-->
<!-- I have some other buttons here as well -->
</ng-template>
</p-column>
Как я могу достичь этого?
Поделиться всем кодом ->
<p-dataTable [globalFilter]="gb" [filterDelay]=1000 [value]="tableData" [alwaysShowPaginator]="true" [rowStyleClass]="setStyle" [rows]="rows" [paginator]="paginate" [alwaysShowPaginator]="false" [resizableColumns]="true" tableStyleClass="table-wrap {{rowClass}}"
[rowsPerPageOptions]="[5,10,20]" expandableRows="{{setExpander}}" [editable]="setEditable" (onRowClick)="handleRowSelect($event)" [lazy]="pagination" [totalRecords]="totalRecords" (onLazyLoad)="loadLazy($event)" [ngClass]="{'paginator-table': pagination}">
<div *ngFor="let col of tableOptions.columns, let index=index, let odd=odd, let even=even">
<p-column *ngIf="col.field" [field]="col.field" [header]="col.header" [sortable]="col.sortable" [filter]="col.filter" [editable]="col.editable" [filterPlaceholder]="col.filterPlaceholder" styleClass="{{col.class}}">
<ng-template let-col let-data="rowData" let-ri="rowIndex" pTemplate="body">
<span *ngIf="!col.field.includes('.')" >{{data[col.field]}}</span>
<!-- <span *ngIf="col.field.includes('.')">{{data[col.field.split('.')[0]][col.field.split('.')[1]]}}</span> this does not work because field is like x.y-->
<a *ngIf="col.field === 'ticket'" target="_blank" href={{link}}{{data[col.field]}}><i class="fa fa-external-link" aria-hidden="true"></i></a>
</ng-template>
</p-column>
</div>
</p-dataTable>
2 ответа
PrimeNG DataTable устарела, вместо этого используйте Table (AKA TurboTable). https://www.primefaces.org/primeng-5-2-0-rc1-released-turbotable/
В любом случае, вы можете получить доступ к вложенному объекту в Data-Table следующим образом:
<p-table [columns]="cols" [value]="data" ... >
...
// Definition of table body
<ng-template pTemplate="body" let-rowData let-columns="columns">
<tr [pSelectableRow]="rowData">
<td *ngFor="let col of columns">
<div *ngIf="col.subfield;then nested_object_content else normal_content"></div>
<ng-template #nested_object_content>
{{rowData[col.field][col.subfield]}}
</ng-template>
<ng-template #normal_content>
{{rowData[col.field]}}
</ng-template>
</td>
</tr>
</ngTemplate>
...
</p-table>
и в вашем компоненте:
public data = [
{
field1: {
subfield1: 'test'
},
field2: 'test',
field3: 'test',
field4: {
subfield4: 'test'
}
}]
this.cols = [
{ field: 'field1', subfield: 'subfield1'},
{ field: 'field2'},
{ field: 'field3'},
{ field: 'field4', subfield: 'subfield4'},
];
Я надеюсь, это поможет вам.:)
В качестве продолжения того, что Бандита сказал о TurboTable: это решение может обрабатывать несколько вложенных свойств вместо одного подполя:
<tr [pSelectableRow]="row">
<td *ngFor="let col of columns">
<span>{{ getCellData(row, col) }}</span>
</td>
</tr>
И в вашем компоненте:
getCellData(row: any, col: any): any {
const nestedProperties: string[] = col.field.split('.');
let value: any = row;
for (const prop of nestedProperties) {
value = value[prop];
}
return value;
}
Вы можете сделать это с помощью Angular Custom Pipe. Образец здесь.
app.component.html
<p-table [columns]="cols" [value]="cars">
<ng-template pTemplate="header" let-columns>
<tr>
<th *ngFor="let col of columns">
{{col.header}}
</th>
</tr>
</ng-template>
<ng-template pTemplate="body" let-rowData let-columns="columns">
<tr>
<td *ngFor="let col of columns">
{{rowData|field:col}}
</td>
</tr>
</ng-template>
</p-table>
app.component.ts
import { Component } from "@angular/core";
@Component({
selector: "my-app",
templateUrl: "./app.component.html",
styleUrls: ["./app.component.css"]
})
export class AppComponent {
cars = [
{
year: 2019,
brand: {
name: "Toyota"
},
color: "White",
passengers: [
{
name: "John"
}
]
},
{
year: 2018,
brand: {
name: "Toyota"
},
color: "White",
passengers: [
{
name: "Suzanne"
}
]
},
{
year: 2017,
brand: {
name: "Toyota"
},
color: "White",
passengers: [
{
name: "Gökhan"
}
]
}
];
cols: any[];
constructor() {}
ngOnInit() {
this.cols = [
{ field: "year", header: "Year" },
{ field: "brand.name", header: "Brand" },
{ field: "color", header: "Color" },
{ field: "passengers.0.name", header: "Passengers" }
];
}
}
Работающий пример здесь.
There is a great article on how to do this in a type safe way here but if safety isn't an issue, you can use Lodash' get
function which saves having to deviate from the PrimeNG basic table use with crazy subfield stuff.
// in .ts file
import {get} from 'lodash';
// give it a different name if you like
_ = get;
// columns
this.columns = [
{field: 'user.address.postcode', header: 'Post Code'}
]
Then in the html
<p-table [columns]="columns" [value]="users$ | async" styleClass="p-
datatable-sm">
<ng-template pTemplate="header" let-columns>
<tr>
<th *ngFor="let col of columns">
{{col.header}}
</th>
</tr>
</ng-template>
<ng-template pTemplate="body" let-rowData let-columns="columns">
<tr>
<td *ngFor="let col of columns">
{{_(rowData, col.field)}}
</td>
</tr>
</ng-template>
</p-table>
this.cols = [
{ field: 'value1', header: 'Value 1' },
{ field: 'value2', header: 'Value 2', element: true },
];
<td class="" *ngFor="let col of columns">
<span class="ui-column-title">{{ col.header }} : </span>
{{col.element ? rowData[col.field].label : rowData[col.field]}}
</td>
Это может быть немного поздно, но я пришел к немного другому решению. У меня есть собственный компонент таблицы, основанный на p-таблице, и я связываю столбцы, строки и т. Д.
Я создал компонент специально для этого, затем привязываю текущую строку и столбец
<ng-template pTemplate="body" let-rowData let-columns="columns">
<tr [pSelectableRow]="rowData">
<td *ngFor="let col of columns">
<app-table-column [column]="col" [row]="rowData"></app-table-column>
</td>
</tr>
</ng-template>
Это мой компонент таблицы-столбца, я делюсь очень простыми вещами, но вы можете улучшить его по своему желанию / необходимости.
Я использую lodash, чтобы получить значение строки на основе поля (столбца), он работает для точек с точками (вложенные свойства) или для плоских свойств.
import { Component, Input, OnInit } from '@angular/core';
import * as moment from 'moment';
import * as _ from 'lodash';
@Component({
template: `
<span>
{{ value }}
</span>
`,
selector: 'app-table-column',
})
export class TableColumnComponent implements OnInit{
@Input() column;
@Input() row;
value: any;
constructor() {}
ngOnInit(): void {
this.parseValue(_.get(this.row, this.column.field));
}
parseValue(value) {
switch (this.column.type) {
case 'date':
this.value = moment(value);
break;
default:
this.value = value;
break;
}
}
}