如何解决PrimeNG的 p-table中 pTemplate='rowexpansion' 的问题?表格的行无法展开
我遇到了一个问题。pTemplate="rowexpansion" 在p-table上不起作用,可能是我的实现方式与PrimeNG的文档不太一致。
在展开方面,我想使用p-button的 (click) 和其中的一个特定函数来获取数据。我在按钮上放了 [pRowToggler]="entry",但它不起作用。有什么可行的实现思路?
文件 component.html
<div style="height: calc(100vh - 230px)">
<p-table
#dt
[columns]="columns"
dataKey="someKey"
[value]="smthliste"
[expandedRowKeys]="expandedRowKeys"
[(selection)]="selectedsmthliste"
selectionMode="multiple"
[totalRecords]="totalElements"
[rowsPerPageOptions]="[10, 50, 100]"
[lazy]="true"
(onLazyLoad)="filtersmthliste($event)"
[scrollable]="true"
scrollHeight="flex"
[paginator]="true"
[(rows)]="numberOfRows"
[showCurrentPageReport]="true"
styleClass="p-datatable-gridlines, p-datatable-striped, p-datatable-sm"
>
<ng-template pTemplate="header" let-columns>
...
</ng-template>
<ng-template
pTemplate="body"
let-entry
let-columns="columns"
let-ri="rowIndex"
>
<tr [attr.data-test]="'smthliste-' + ri">
<td
class="sticky-checkbox"
[attr.data-test]="'smthliste-' + ri + '-column-checkbox'"
>
<p-tableCheckbox
[name]="'checkbox' + ri"
[value]="entry"
></p-tableCheckbox>
</td>
<td class="sub-super-elements-td sticky-checkbox">
<div class="sub-super-elements">
@if (!rowExpansionExpanded.includes(entry.someKey)) {
<p-button
class="sub-super-elements__button-super"
[pRowToggler]="smthliste"
(click)="onClickExpansion('super', entry)"
data-test="button-super"
[icon]="'pi pi-directions'"
[plain]="true"
pRipple
[rounded]="true"
size="large"
[text]="true"
type="button"
></p-button>
}
@if (!rowExpansionExpanded.includes(entry.someKey)) {
<p-button
class="sub-super-elements__button-sub"
(click)="onClickExpansion('sub', entry)"
data-test="button-sub"
[icon]="'pi pi-directions'"
[plain]="true"
pRipple
[pRowToggler]="entry"
[rounded]="true"
size="large"
[text]="true"
type="button"
></p-button>
}
@if (rowExpansionExpanded.includes(entry.someKey)) {
<p-button
class="sub-super-elements__button-close"
(click)="onClickExpansion('close', entry)"
data-test="button-close"
[icon]="'pi pi-chevron-up'"
[plain]="true"
pRipple
[pRowToggler]="entry"
[rounded]="true"
size="large"
[text]="true"
type="button"
></p-button>
}
</div>
</td>
</tr>
...
<ng-template pTemplate="rowexpansion" let-entry>
<tr>
<td colspan="999">
<div class="p-3">
<div>DEBUG: {{ entry.someKey }} | expansion length: {{ entry.expansion?.length }}</div>
<app-smthliste-row-expansion
[...]="..."
[columns]="columns"
[...]="
...
"
[...]="..."
[onClickExpansion]="onClickExpansion"
[(pTableSelection)]="selectedsmthliste"
[rowExpansionExpanded]="rowExpansionExpanded"
[selectedUserGroup]="sessionService...."
[smthlisten]="entry.expansion"
[...]="..."
[...]="..."
>
</app-smthliste-row-expansion>
</div>
</td>
</tr>
</ng-template>
</p-table>
文件 component.ts
...
onClickExpansion(type: 'super' | 'sub' | 'close', smthliste: Smthliste) {
this.table.toggleRow(smthliste);
console.log('1. onClick called', type, smthliste.someKey);
if (type === 'close') {
const indexOf = this.rowExpansionExpanded.indexOf(someliste.someKey);
if (indexOf >= 0) {
this.rowExpansionExpanded.splice(indexOf, 1);
}
delete this.expandedRowKeys[smthliste.someKey];
return;
}
if (this.rowExpansionExpanded.includes(smthliste.smthKey)) {
console.log('2. Already expanded, returning');
return;
}
console.log('3. Calling API for', type);
const superSubSmthlistenObservable =
type === 'super'
? this.smthlisteService.getSuperSmthlisten(smthliste)
: this.smthlisteService.getSubSmthlisten(smthliste);
superSubSmthlistenObservable.subscribe({
next: (superSubSmthlisten) => {
console.log('4. API returned', superSubSmthlisten);
if (!superSubSmthlisten || superSubSmthlisten.length === 0) {
this.messageService.add({
severity: 'info',
summary: 'No data',
detail: `No ${type} elements found for ${smthliste.someKey}`,
});
return; // Do not expand empty row
}
smthliste.expansion = superSubSmthlisten;
this.rowExpansionExpanded.push(smthliste.someKey);
this.expandedRowKeys[smthliste.someKey] = true;
this.cdr.detectChanges();
},
error: (err) => {
console.error('API ERROR:', err);
},
});
}
...
this.dt.toggleRow(entry); // It doesn't work
Delete(点击)不起作用。
只有这个能工作,但这并不是我想要的:
<!-- ...existing code... -->
<ng-template pTemplate="body">
<tr >
@if (rowExpansionExpanded.includes(entry.someKey)) {
<tr>
<td colspan="999">
<div class="p-3">
<div>DEBUG: </div>
<app-smthliste-row-expansion
>
</app-smthliste-row-expansion>
</div>
</td>
</tr>
}
</ng-template>
解决方案
移除切换控件,确保你的 p-button 只触发你的逻辑,它是为“无逻辑的切换”场景设计的。移除它后,你就可以通过 onClickExpansion 函数获得完全的控制。
要渲染 pTemplate="rowexpansion",PrimeNG会检查该行的 dataKey 是否存在于 expandedRowKeys 对象中。你现在是手动在管理这个,但你必须确保对象引用会更新,以便Angular能检测到变化。
dataKey匹配: 确保你在<p-table>中的dataKey="someKey"与属性名entry.someKey完全一致。如果不匹配,PrimeNG就不会知道要展开哪一行。- 展开模板的位置: 确保你的
<ng-template pTemplate="rowexpansion" let-entry>是<p-table>的直接子元素。它应该在pTemplate="body"之外但在p-table标签内。 - 可变vs不可变: PrimeNG常常使用
ChangeDetectionStrategy.OnPush。如果你只是简单地执行this.expandedRowKeys[key] = true,对象引用仍然相同,表格可能不会重新渲染。请始终使用扩展运算符{ ...this.expandedRowKeys }来创建一个新的引用。
请按如下操作:
- 从按钮中移除
[pRowToggler]。 - 确保表格上的
dataKey是"someKey"。 - 在订阅中用不可变的方式更新
expandedRowKeys。 - 在表格绑定中使用
this.expandedRowKeys:[expandedRowKeys]="expandedRowKeys"。
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。