Skip to content

Commit 7768bb7

Browse files
committed
docs: BACKLOG — DataTable filter popover dismiss-on-overlay-click upstream PR
Adds a row tracking PrimeVue issues #8537 (MultiSelect) and #8213 (TreeSelect) — DataTable filter popover dismissing on clicks inside a body-portaled overlay widget. The bug shares its root-cause family with the popover-dismiss issue we already fixed downstream in `SettingsPopover.vue` (commit `1ccd62cff`), so the row documents both surfaces. A community contributor (`VaishnaviD5900`) submitted PR [primevue#8566](primefaces/primevue#8566) addressing both issues — uses PrimeVue's existing `data-pc-section` attribute via `closest()` rather than a class-name whitelist, which is cleaner than what our downstream workaround does. The row notes a small follow-up cleanup we can do once that PR merges: swap the hardcoded PrimeVue overlay class selectors in our SettingsPopover for the same `data-pc-section` lookup, dropping the class-name-tracking burden. Also captures a separate-path idea for a helper composable (`useOverlayAwareClickOutside()`) to expose this pattern for downstream consumers — explicitly deferred until #8566 merges so the in-flight bug-fix isn't conflated with an API-design ask. Signed-off-by: Oliver Sluke <22557015+oliversluke@users.noreply.github.com>
1 parent a31cf4f commit 7768bb7

1 file changed

Lines changed: 1 addition & 0 deletions

File tree

BACKLOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ before client work starts.
5454
| Low | Group-by sticky header — make it conditional on expand state | PrimeVue 4's DataTable in `rowGroupMode="subheader"` unconditionally pins each cluster header sticky to the top of the scroll viewport (`@primeuix/styles/dist/datatable/index.mjs`: `.p-datatable-scrollable-table > .p-datatable-tbody > .p-datatable-row-group-header { position: sticky; z-index: 1 }`). Sticky reads well when the cluster is **expanded** (the header anchors while you scroll through the cluster's rows), but adds visual noise when the cluster is **collapsed** (no rows below to scroll past — the pinned header just gets replaced by the next pinned header). PrimeVue does NOT add an expand-state class to the header row, so the conditional behaviour has to be synthesised client-side: watch `expandedRowGroups`, find each `tr.p-datatable-row-group-header`, set a `data-tvh-group-expanded` attribute, then CSS targets `tr.p-datatable-row-group-header:not([data-tvh-group-expanded='true']) { position: static }`. Imperative DOM touching (Vue's scoped CSS doesn't reach inside PrimeVue's table body) — fragile, but small. Estimated ~1 hr. **Pre-empt with the upstream PR row below** — if PrimeVue adds the CSS hook themselves, this row deletes cleanly. |
5555
| Low | Upstream PR to PrimeVue — add `expanded` / `collapsed` class to row-group header | PrimeVue 4's DataTable subheader-grouping currently renders the cluster header `<tr>` with a single static class (`p-datatable-row-group-header`) regardless of expand state. Consumers wanting to style the header differently when expanded vs collapsed (e.g. sticky-only-when-expanded — see the row above) have to monkey-patch via DOM observation. The fix is a one-line CSS hook in the component template — add `'p-row-group-expanded': isRowGroupExpanded(row)` (or equivalent dynamic class binding) alongside the existing `cx('rowGroupHeader')` call at `primevue/datatable/index.mjs:1771`. Additive, safe for every existing consumer, generally useful — every grouped-table user benefits. **Lands as a standalone upstream PR to the PrimeVue repo** per the same pattern we use for the tvheadend upstream PRs. Once it lands and we bump our PrimeVue dep, the client-side workaround row above becomes a tiny CSS rule (`tr.p-datatable-row-group-header:not(.p-row-group-expanded) { position: static }`) and we can delete the imperative watcher. |
5656
| Low | Upstream PR to PrimeVue — fix VirtualScroller + row grouping (3-year-old bug) | PrimeVue 4's DataTable with `groupRowsBy="<field>"` + `rowGroupMode="subheader"` + `virtualScrollerOptions` is broken: when groups are collapsed (only headers visible, no data rows), the VirtualScroller spacer (`.p-datatable-virtualscroller-spacer`) emits a 0 px size and doesn't absorb the unused vertical space. PrimeVue's `.p-datatable-flex-scrollable { flex: 1; height: 100% }` rule combined with `tbody { min-height: 100% }` then forces the few visible rows to stretch to fill the table's `scrollHeight="flex"` container — DVR Finished with a collapsed-group view renders rows at ~145 px each instead of the configured `itemSize: 36`. Symptom: visible flicker + row-height jitter during scroll. **Existing tickets** (all open, no upstream fix after three years): [primevue#4109](https://github.com/primefaces/primevue/issues/4109) (open since 2023-07, 17 reactions, still seen on 4.3.6), [primevue#7339](https://github.com/primefaces/primevue/issues/7339) (open 2025-02), [primevue#6222](https://github.com/primefaces/primevue/issues/6222) (Tailwind preset variant), [primevue#3491](https://github.com/primefaces/primevue/issues/3491) (Expand + VirtualScroll), [primereact#4577](https://github.com/primefaces/primereact/issues/4577) (closed stale), [primereact#5036](https://github.com/primefaces/primereact/issues/5036). Same family of bugs in PrimeNG too. **Workaround we've adopted**: gate `virtualScrollerOptions` to `undefined` when `groupField` is set (DataGrid.vue's `effectiveVirtualScrollerOptions` computed). For EPG Table specifically the bug no longer matters at scale — grouped mode uses stub-rows + per-cluster on-expand fetches so the DOM only ever holds ~100 cluster headers + the events of the currently-expanded clusters, well within unvirtualised render budget. Demoted to Low because the perf hazard is bounded by user behaviour (must expand many large clusters to feel it). For DVR / Channels grouped views (smaller datasets) the workaround is invisible. Filed for the day we either revisit virtual scroll for a specific use case or the upstream lands. **Status 2026-05-18**: precise diagnosis posted as a comment on [primevue#4109](https://github.com/primefaces/primevue/issues/4109#issuecomment-4478388445) — identifies the bug as TWO independent spacer-drift sources (collapsed body rows occupying `items[]` slots without rendering + auto-injected subheader rows rendering without being in `items[]`), supplies a minimal repro on v4.5.5, and proposes two fix directions. Empirically confirmed via isolated spike (`~/primevue-bug-spike/`): a downstream items-reshape fixes Source 1 only — Source 2 (header height 39.75 px vs itemSize 36 px, plus header count not in spacer math) is structural to the subheader render path and not fixable downstream. Spike kept behind `ENABLE_GROUPED_VIRTUAL_SCROLL` flag (currently `false`) in TableView.vue so flipping is trivial the day a fix lands. **Upstream PR submitted**: [primevue#8579](https://github.com/primefaces/primevue/pull/8579) ("Fixed #4109 - DataTable + VirtualScroller spacer drift with rowGroupMode subheader") — adds a `getItemSize(index)` callback to VirtualScroller; DataTable supplies a function that returns `itemSize + measured group-header height` at cluster boundaries and `0` for hidden rows in collapsed clusters. Corrects both drift sources via one mechanism, ~373 LOC additions, 14 new unit specs. State: OPEN, awaiting maintainer review. When merged + we bump PrimeVue, the spike flag flips to `true` and the `effectiveVirtualScrollerOptions` workaround at `DataGrid.vue:1071-1080` can retire. |
57+
| Low | Upstream fix to PrimeVue — DataTable column-filter popover dismisses on body-portaled overlay clicks | PrimeVue 4's DataTable column-filter popover dismisses the moment the user clicks an option inside an embedded MultiSelect / TreeSelect / Select / DatePicker. Root cause: those widgets render their overlay panels under `<body>` via PrimeVue's portal (default `appendTo: 'body'`); DataTable's document-level click-outside handler sees option clicks as "outside" and closes the filter popover before the checkbox / option toggle commits. Same family as `EpgTableOptions`' popover-dismiss bug fixed downstream at `src/webui/static-vue/src/components/SettingsPopover.vue:153-169` (commit `1ccd62cff`) via a whitelist pattern — `composedPath()` membership check that excludes any element matching a known PrimeVue overlay selector (`.p-multiselect-overlay`, `.p-select-overlay`, `.p-datepicker-panel`, `.p-tooltip`). **Existing tickets** (both open): [primevue#8537](https://github.com/primefaces/primevue/issues/8537) (MultiSelect, May 2026), [primevue#8213](https://github.com/primefaces/primevue/issues/8213) (TreeSelect, earlier in 2026). The MultiSelect issue body explicitly cites #8213 as the same root cause. **Upstream PR submitted**: [primevue#8566](https://github.com/primefaces/primevue/pull/8566) ("fix(datatable): fix filter overlay closing when interacting with nested overlay components") by `VaishnaviD5900`. 6+/6- in `packages/primevue/src/datatable/ColumnFilter.vue` — uses `closest('[data-pc-section="panel"], [data-pc-section="overlay"]')` to detect any active PrimeVue overlay via PrimeVue's existing `data-pc-section` attribute convention (cleaner than the class-list whitelist we used downstream — no maintenance as new components ship). Closes both #8537 AND #8213. State: OPEN, awaiting maintainer review. **Workaround we adopted downstream**: the class-list whitelist in `SettingsPopover.vue`'s outside-click handler — covers our EpgTableOptions popover where Genre + Tag MultiSelects live. **Cleanup follow-up after the PR lands**: swap the hardcoded `PRIMEVUE_OVERLAY_SELECTORS` array in `SettingsPopover.vue` for a `closest('[data-pc-section="panel"], [data-pc-section="overlay"]')` check, mirroring the PR's approach. Drops the maintenance burden of tracking PrimeVue overlay class names as new widgets get embedded. ~10 LOC delta in one file. **Follow-up idea (separate path, defer until after #8566 merges)**: file a SECOND issue / comment-on-merged-PR titled "Consider exposing this pattern as a helper for downstream consumers" (e.g. `useOverlayAwareClickOutside()` composable). The `data-pc-section` attribute is already public-ish convention; a documented helper would make the pattern discoverable for any consumer popover that embeds PrimeVue overlays. Lower-noise scope, properly framed as API design rather than bug fix. Our SettingsPopover whitelist would then collapse to a one-line import. Don't conflate with the in-flight bug-fix PR. |
5758
| Low | Upstream `PO_GROUPABLE` prop-opt flag — server-driven groupable-fields metadata | Today every grid that wants the Group by section declares a per-class `groupableFields: GroupableFieldDef[]` allowlist on the client side (DVR list views' `DVR_GROUPABLE_FIELDS` in `dvrFieldDefs.ts`; EPG TableView's inline `groupableFields` array). This is the path 2(a) decision made during the grouping work — ship the client-side allowlist first, file a server-side `PO_GROUPABLE` flag as a follow-up that retires the per-class allowlists. **Fix shape**: (1) add `PO_GROUPABLE` bit to `src/prop.h` next to `PO_PASSWORD` / `PO_DURATION` (next free bit). (2) Emit it from `prop_serialize()` at `src/prop.c:527-543` — `if (opts & PO_GROUPABLE) htsmsg_add_bool(m, "groupable", 1);` matching the existing flag-emit pattern. (3) Annotate the C props that the v2 UI currently declares groupable: `dvr_entry`'s `channel` + `config_name` + `start` (`src/dvr/dvr_db.c`); `mpegts_service`'s grouping candidates if extended later; etc. Strictly opt-in. **Client follow-up after server lands**: extend `IdnodeProp` (`src/webui/static-vue/src/types/idnode.ts`) to read `groupable: boolean`; IdnodeGrid derives `groupableFields` from the active class metadata instead of taking it as a prop; delete per-class allowlists. The `groupKey` projector (for the date-only Start grouping) stays client-side because it's a display-formatting concern that doesn't belong on the wire — the server flag just says "this field is groupable," the client decides how to project it. **Lands as a standalone upstream PR** per the "Independent upstream PRs" pattern — commit message + body must NOT reference v2 Vue UI work, PR #2098, or any v2 planning docs (the flag is generally useful and Classic UI could grow a grouping affordance later too). Pattern matches the proposed `PO_MANDATORY` row in the Infrastructure section. (*server-side*) |
5859
| Low | Responsive column-header polish — multi-line wrap on narrow widths instead of ellipsis | Today's column-header chrome ellipsises long labels on narrow widths (resolved in DMC's PR-review C2 fix — `.p-datatable-column-title { min-width: 0; overflow: hidden; text-overflow: ellipsis; }` in `primevue.css` plus a default `title` attribute on the `<th>` via DataGrid's `mergeColumnPt` so the user can hover to read the full label). On a tablet or narrow desktop where a column has been dragged narrow but vertical room remains, allowing the label to WRAP onto a second line ("Network connection time" → 2 lines, both fully visible) would read better than ellipsising. PrimeVue's `<th>` enforces `white-space: nowrap` via `.p-datatable-resizable-table` (see `@primeuix/styles/dist/datatable/index.mjs` — the same stylesheet that drove the C2 investigation), so a wrap option needs an override on that nowrap rule plus a per-column or per-grid opt-in (to keep one-line headers as the default for compact desktop layouts where wrap would feel too tall). Phone-width grids use card layout (different rendering path entirely) and aren't affected. Edge case worth a focused design pass once specific complaints surface — not blocking because the C2 fix already handles the no-room case via ellipsis + the hover-to-read tooltip. |
5960
| Med | Auto-fit column width — fit-to-content (true autofit) | The kebab menu's "Reset to default width" entry (in `ColumnHeaderMenu.vue`, wired via DataGrid → IdnodeGrid's `onResetWidthColumn`) clears the user's persisted width so the column reverts to its declared `def.width` or the 160 px fallback. That's a "reset" — it does NOT compute the actual content-fitting width. The natural user expectation for "auto-fit" is the latter: measure the widest cell content + the header label and set the column to that width (with a minimum to keep things readable, plus padding for chrome). Implementation shape: walk the column's rendered td cells in the current page (or sample a fixed number for perf on long lists), measure each via `offsetWidth` of a shadow span at the same font + computed style, take the max, clamp between a sensible floor (~80 px) and ceiling (~600 px), then write to `colPrefs[field].width` via the existing `colPrefs` ref. PrimeVue's `column-resize-mode="expand"` complicates this — it caches resize widths in its own `<style>` element with `!important nth-child(N)` rules; we already destroy that on reset (DataGrid `onResetWidth`) but auto-fit would need the same destroy + a fresh write. Add as a SECOND menu entry once shipped, alongside the existing reset — they're related but distinct user intents. Filed as Med because it's the natural mental model and likely the more-frequently-wanted action. |

0 commit comments

Comments
 (0)