在 p- table 中使用第二行标题( 列组) 时可调整的相册已损坏
作者: domenicotds创建于 2026年3月20日更新于 2026年9月17日
标签Type: Buggood first issueResolution: Stale
Describe the bug When adding a second header row to group columns (e.g. using colspan on a above the main header row), the column resize functionality breaks: resizing a column affects the wrong column instead. Root cause The internal method _totalTableWidth() collects column widths using: let headers = DomHandler.find(tableHead, "tr > th"); This selector matches all elements across all rows in the , including the group header row. As a result, the widths array contains more entries than there are real columns (e.g. 12 group + 33 column = 45 entries instead of 33). When updateStyleElement uses this array with the colIndex of the resized column, it applies the new width to the wrong nth-child index, causing an incorrect column to be resized. To Reproduce Create a p-table with resizableColumns="true" and scrollable="true" Add a custom header template with two rows: the first with grouped cells, the second with the actual column cells with pResizableColumn Try to resize any column by dragging its resize handle Observe that a different column gets resized instead of the one being dragged Expected behavior Column resize should affect only the dragged column, regardless of how many rows are present in the . Actual behavior The resized column is offset by the number of elements in the group header row. For example, with 12 group headers, resizing column at index 3 actually resizes column at index 3 within the full 45-element array — which corresponds to a different visual column. Proposed fix In _totalTableWidth(), change the selector from "tr > th" to "tr:last-child > th" so that only the elements of the last header row (the actual columns) are collected: // BEFORE let headers = DomHandler.find(tableHead, "tr > th"); // AFTER let headers = DomHandler.find(tableHead, "tr:last-child > th"); This is a one-line fix that makes the width array length consistent with the actual number of resizable columns. Workaround Monkey-patching _totalTableWidth on the Table instance in ngAfterViewInit: ngAfterViewInit(): void { this.patchResizeTableCells(); } private patchResizeTableCells(): void { if (!this.dtGrid) return; (this.dtGrid as any)._totalTableWidth = () => { if (!this.columnHeaderGroups?.length) { const tableHead = this.dtGrid.el.nativeElement.querySelector('[data-pc-section="thead"]'); const headers = tableHead.querySelectorAll('tr > th'); return Array.from(headers).map((h: any) => h.offsetWidth); } const tableHead = this.dtGrid.el.nativeElement.querySelector('[data-pc-section="thead"]'); const rows = tableHead.querySelectorAll('tr'); const lastRow = rows[rows.length - 1] as HTMLTableRowElement; const headers = lastRow.querySelectorAll('th'); const widths: number[] = []; headers.forEach((header: HTMLElement) => { widths.push(header.offsetWidth); }); return widths; } };…
let headers = DomHandler.find(tableHead, "tr > th"); This selector matches all // BEFORE let headers = DomHandler.find(tableHead, "tr > th"); // AFTER let headers = DomHandler.find(tableHead, "tr:last-child > th"); This is a one-line fix that makes the width array length consistent with the actual number of resizable columns. Workaround Monkey-patching _totalTableWidth on the Table instance in ngAfterViewInit: ngAfterViewInit(): void { this.patchResizeTableCells(); } private patchResizeTableCells(): void { if (!this.dtGrid) return; (this.dtGrid as any)._totalTableWidth = () => { if (!this.columnHeaderGroups?.length) { const tableHead = this.dtGrid.el.nativeElement.querySelector('[data-pc-section="thead"]'); const headers = tableHead.querySelectorAll('tr > th'); return Array.from(headers).map((h: any) => h.offsetWidth); } const tableHead = this.dtGrid.el.nativeElement.querySelector('[data-pc-section="thead"]'); const rows = tableHead.querySelectorAll('tr'); const lastRow = rows[rows.length - 1] as HTMLTableRowElement; const headers = lastRow.querySelectorAll('th'); const widths: number[] = []; headers.forEach((header: HTMLElement) => { widths.push(header.offsetWidth); }); return widths; } };…内容来源: primefaces/primeng