From a80c38a1053e5c7543a212f2a65383f449662c39 Mon Sep 17 00:00:00 2001 From: Yordan Stoyanov Date: Thu, 10 Sep 2026 15:22:15 +0200 Subject: [PATCH 1/5] docs(datagrid-web): add openspec change for custom pagination position Scopes WC-3548 (custom pagination ignoring Position of pagination), the Data Grid 2 half of the bug WC-3505 fixed for Gallery. --- .../.openspec.yaml | 2 + .../pagination-position-not-honored/design.md | 50 +++++++++++++++++ .../proposal.md | 40 ++++++++++++++ .../spec.md | 55 +++++++++++++++++++ .../pagination-position-not-honored/tasks.md | 21 +++++++ 5 files changed, 168 insertions(+) create mode 100644 packages/pluggableWidgets/datagrid-web/openspec/changes/pagination-position-not-honored/.openspec.yaml create mode 100644 packages/pluggableWidgets/datagrid-web/openspec/changes/pagination-position-not-honored/design.md create mode 100644 packages/pluggableWidgets/datagrid-web/openspec/changes/pagination-position-not-honored/proposal.md create mode 100644 packages/pluggableWidgets/datagrid-web/openspec/changes/pagination-position-not-honored/specs/datagrid-custom-pagination-position/spec.md create mode 100644 packages/pluggableWidgets/datagrid-web/openspec/changes/pagination-position-not-honored/tasks.md diff --git a/packages/pluggableWidgets/datagrid-web/openspec/changes/pagination-position-not-honored/.openspec.yaml b/packages/pluggableWidgets/datagrid-web/openspec/changes/pagination-position-not-honored/.openspec.yaml new file mode 100644 index 0000000000..e8cda9e50e --- /dev/null +++ b/packages/pluggableWidgets/datagrid-web/openspec/changes/pagination-position-not-honored/.openspec.yaml @@ -0,0 +1,2 @@ +schema: spec-driven +created: 2026-09-10 diff --git a/packages/pluggableWidgets/datagrid-web/openspec/changes/pagination-position-not-honored/design.md b/packages/pluggableWidgets/datagrid-web/openspec/changes/pagination-position-not-honored/design.md new file mode 100644 index 0000000000..8c8714186b --- /dev/null +++ b/packages/pluggableWidgets/datagrid-web/openspec/changes/pagination-position-not-honored/design.md @@ -0,0 +1,50 @@ +## Context + +`pagingPosition` (`"top" | "bottom" | "both"`) already drives the built-in `Pagination` control: + +- `WidgetTopBar.tsx`: `` +- `WidgetFooter.tsx`: `` + +Custom pagination (the `customPagination` widgets placeholder, shown when `useCustomPagination` is true and `pagination === "buttons"`) is wired separately and ignores position: + +- `WidgetFooter.tsx`: `{customPagination.get()}` — always renders, no position check. +- `WidgetTopBar.tsx`: no custom pagination branch at all. +- `Datagrid.editorPreview.tsx`: `useCustomPagination()` returns `props.useCustomPagination` with no position check; only rendered in the footer's `CustomPagination`. +- `Datagrid.editorConfig.ts` currently hides `pagingPosition` from the properties panel whenever `useCustomPagination` is true (added when custom pagination shipped, as a stopgap since the property had no effect). Once position has an effect, hiding it is wrong. + +Gallery (`gallery-web`) had the exact same defect and fixed it under WC-3505 (`GalleryFooterControls.tsx`, `GalleryTopBarControls.tsx`), which was explicitly scoped to exclude Data Grid 2 to keep that PR reviewable. This change ports the same rule to Data Grid 2. Data Grid 2's bars have no alignment/slot-resolution machinery (`resolveSlots`) — that part of the Gallery change was about a _different_, already-working design property (pagination alignment) that Data Grid 2 doesn't have — so none of that machinery is needed here. + +## Goals / Non-Goals + +**Goals:** + +- Custom pagination widgets render in the top bar when `pagingPosition === "top"`, in the footer when `"bottom"`, and exactly once (footer) when `"both"`. +- Editor preview matches runtime for all three positions. +- `pagingPosition` stays visible/editable in Studio Pro when custom pagination is enabled. +- A `check()` warning fires for `useCustomPagination && pagingPosition === "both"`, mirroring Gallery's wording/severity. + +**Non-Goals:** + +- No pagination-alignment design property for Data Grid 2 (out of scope per WC-3505's own scoping note — Data Grid 2 doesn't have this property; adding one is a feature request, not this fix). +- No changes to `widget-plugin-grid` or `data-widgets` — the built-in `Pagination` component's own position logic is already correct and untouched. +- No changes to the unrelated `_datagrid.scss` top-bar container-query typo noted in the Gallery proposal as a separate, deliberately excluded fix. + +## Decisions + +- **Reuse the existing `pgConfig.pagingPosition` value already threaded into both bars** rather than introducing new state. `usePaginationConfig()` already exposes `pagingPosition` and `customPaginationEnabled`; both bars just need an additional condition. +- **"Both" resolves to footer-only, not top-bar-only or duplicated.** Same reasoning as Gallery: `customPagination.get()` returns the actual configured widgets placeholder — rendering it in two places would duplicate widget instances, DOM ids, and MobX-backed state. Footer is chosen (not top bar) purely for consistency with Gallery's precedent and because it's the current de facto behavior developers have already built pages against. +- **Condition shape mirrors Gallery exactly** for auditability: + - Footer: `pgConfig.customPaginationEnabled && pgConfig.pagingPosition !== "top"` + - Top bar: `pgConfig.customPaginationEnabled && pgConfig.pagingPosition === "top"` +- **Drop `pagingPosition` from the `hidePropertiesIn` call** in `Datagrid.editorConfig.ts` for the `useCustomPagination` branch; keep `showPagingButtons` hidden there since it only affects the built-in control's prev/next buttons, which custom pagination replaces entirely. +- **Warning lives in `consistency-check.ts`** (not inlined in `editorConfig.ts`) to match this package's existing convention — `editorConfig.ts` re-exports `check` from `consistency-check.ts`, and all other structural warnings/errors already live there. +- **No new capability abstraction (no `resolveSlots`-equivalent).** Data Grid 2's bars have exactly one pagination-bearing slot each (`pb-end` / `tb-end`); there's no counter/load-more displacement problem to solve, so a plain boolean condition is the right level of complexity — introducing a slot-resolution function here would be solving a problem this widget doesn't have. + +## Risks / Trade-offs + +- **[Risk]** Existing apps that already set `pagingPosition` to `"top"` or `"both"` while using custom pagination will see a visible layout change (widgets moving from footer to top bar, or a warning appearing) on upgrade. → **Mitigation**: this is the bug fix itself — the property was always meant to have this effect, per its own description in Studio Pro ("Position of pagination"). Documented in the changelog as a behavior fix, not flagged as breaking (no API/prop shape change). +- **[Risk]** Unhiding `pagingPosition` when custom pagination is on could surprise developers who never noticed the property while it was hidden. → **Mitigation**: matches Gallery's existing (never-hidden) behavior for the same property; the new `check()` warning immediately explains the "both" caveat if they hit it. + +## Migration Plan + +No data migration. Widget-level runtime/config-only change, shipped as a normal `datagrid-web` release. No rollback complexity beyond a standard revert. diff --git a/packages/pluggableWidgets/datagrid-web/openspec/changes/pagination-position-not-honored/proposal.md b/packages/pluggableWidgets/datagrid-web/openspec/changes/pagination-position-not-honored/proposal.md new file mode 100644 index 0000000000..a2adf458bb --- /dev/null +++ b/packages/pluggableWidgets/datagrid-web/openspec/changes/pagination-position-not-honored/proposal.md @@ -0,0 +1,40 @@ +## Why + +Data Grid 2's "Position of pagination" property (`pagingPosition`: Above grid / Below grid / Both) already gates the built-in `Pagination` control in both `WidgetTopBar` and `WidgetFooter`. Custom pagination — the developer-supplied widgets placeholder shown when "Custom pagination" is enabled — ignores it completely: `WidgetFooter` renders the custom pagination widgets unconditionally whenever custom pagination is on, and `WidgetTopBar` never renders them at all. Setting "Above grid" has no effect; the widgets always render below the grid (WC-3548). + +Gallery had the identical bug and fixed it under WC-3505, which explicitly scoped Data Grid 2 out to keep that change reviewable ("DataGrid 2's custom-pagination position bug ... needs its own ticket"). This change is that ticket. Unlike Gallery, Data Grid 2's editor preview already agrees with its runtime (both footer-only today), so there is no preview/runtime divergence to fix here — only the ineffective property, plus a related Studio Pro editor-config quirk: when custom pagination is enabled, `pagingPosition` is currently hidden from the properties panel entirely (a pre-existing mitigation for the very bug this change fixes), so once the position has a real effect it must be shown again. + +## What Changes + +- **`WidgetTopBar` renders custom pagination widgets when `pagingPosition` is `"top"`.** Today it only ever renders the built-in `Pagination` component and never checks for custom pagination. +- **`WidgetFooter` renders custom pagination widgets only when `pagingPosition` is not `"top"`** (i.e. `"bottom"` or `"both"`), instead of unconditionally. +- **`"Both"` renders custom pagination once, in the footer**, not in both bars — duplicating the `customPagination` widgets placeholder would duplicate widget instances, DOM ids, and state, exactly as identified in the Gallery fix. +- **A design-time `check()` warning** is added for the `useCustomPagination && pagingPosition === "both"` combination, explaining that custom pagination renders once (below the grid) and suggesting the developer pick a single position. +- **`Datagrid.editorConfig.ts` stops hiding `pagingPosition`** when custom pagination is enabled — the property now has an effect, so it must stay visible and editable (mirrors Gallery, which never hid it in this case). `showPagingButtons` stays hidden for custom pagination since it only affects the built-in control. +- **`Datagrid.editorPreview.tsx`** picks up the same top/footer/both rule so preview continues to agree with runtime. + +## Capabilities + +### New Capabilities + +- `datagrid-custom-pagination-position`: where Data Grid 2's custom pagination widgets render relative to the grid, honouring `Position of pagination` ("Above grid" / "Below grid" / "Both"), including the single-render rule for "Both", the accompanying design-time warning, and parity between runtime and editor preview. + +### Modified Capabilities + +_None — `openspec/specs/` in this package currently documents no pagination-placement capability, so this is captured as a new capability rather than a delta._ + +## Impact + +`packages/pluggableWidgets/datagrid-web` + +- `src/components/WidgetFooter.tsx`, `src/components/WidgetTopBar.tsx` — gate custom pagination rendering on `pagingPosition`. +- `src/Datagrid.editorConfig.ts` — stop hiding `pagingPosition` for custom pagination; add the `"both"` + custom pagination warning (in `src/consistency-check.ts`, which `editorConfig.ts` re-exports `check` from). +- `src/Datagrid.editorPreview.tsx` — mirror the top/footer/both placement rule for the preview's `CustomPagination` placeholder. +- `src/components/__tests__/` — unit tests covering `pagingPosition` × custom pagination for both bars; `consistency-check` tests for the new warning. +- `CHANGELOG.md` — user-facing entry: custom pagination now respects "Position of pagination". + +Cross-cutting + +- No shared-package changes (`widget-plugin-grid` is untouched; Data Grid 2 has no pagination-alignment design property, unlike Gallery, so no `data-widgets` module changes are needed). +- No breaking changes: `pagingPosition` and `useCustomPagination` keep their existing keys and defaults; only the rendering behavior for an already-visible property changes. +- Release vehicle: `datagrid-web` patch/minor release; version bump and changelog entry added at release time per repo convention. diff --git a/packages/pluggableWidgets/datagrid-web/openspec/changes/pagination-position-not-honored/specs/datagrid-custom-pagination-position/spec.md b/packages/pluggableWidgets/datagrid-web/openspec/changes/pagination-position-not-honored/specs/datagrid-custom-pagination-position/spec.md new file mode 100644 index 0000000000..dd371d1e41 --- /dev/null +++ b/packages/pluggableWidgets/datagrid-web/openspec/changes/pagination-position-not-honored/specs/datagrid-custom-pagination-position/spec.md @@ -0,0 +1,55 @@ +## ADDED Requirements + +### Requirement: Custom pagination honors the position setting + +When custom pagination is enabled, Data Grid 2 SHALL render the custom pagination widgets according to the `pagingPosition` property ("Above grid" / "Below grid" / "Both") instead of always rendering them in the footer. + +#### Scenario: Position set to "Above grid" + +- **WHEN** custom pagination is enabled and `pagingPosition` is `"top"` +- **THEN** the custom pagination widgets render in the top bar +- **AND** the custom pagination widgets do not render in the footer + +#### Scenario: Position set to "Below grid" + +- **WHEN** custom pagination is enabled and `pagingPosition` is `"bottom"` +- **THEN** the custom pagination widgets render in the footer +- **AND** the custom pagination widgets do not render in the top bar + +#### Scenario: Position set to "Both" + +- **WHEN** custom pagination is enabled and `pagingPosition` is `"both"` +- **THEN** the custom pagination widgets render exactly once, in the footer +- **AND** the custom pagination widgets do not also render in the top bar + +### Requirement: Editor preview matches runtime placement + +Studio Pro's editor preview for Data Grid 2 SHALL place the custom pagination placeholder using the same `pagingPosition` rule as the runtime, so the page editor never disagrees with the running app. + +#### Scenario: Preview reflects "Above grid" + +- **WHEN** custom pagination is enabled and `pagingPosition` is `"top"` in the page editor +- **THEN** the custom pagination placeholder renders above the grid preview + +#### Scenario: Preview reflects "Below grid" or "Both" + +- **WHEN** custom pagination is enabled and `pagingPosition` is `"bottom"` or `"both"` in the page editor +- **THEN** the custom pagination placeholder renders below the grid preview, exactly once + +### Requirement: Position property remains configurable with custom pagination + +The `pagingPosition` property SHALL remain visible and editable in the Studio Pro properties panel when custom pagination is enabled, since the property now affects rendering. + +#### Scenario: Custom pagination enabled + +- **WHEN** a developer enables custom pagination on a Data Grid 2 configured with `pagination` set to `"buttons"` +- **THEN** the "Position of pagination" property remains visible and editable in the properties panel + +### Requirement: Design-time warning for "Both" with custom pagination + +Data Grid 2's consistency check SHALL emit a warning when custom pagination is enabled and `pagingPosition` is `"both"`, explaining that the widgets render once, below the grid. + +#### Scenario: Custom pagination with "Both" position configured + +- **WHEN** a developer enables custom pagination and sets `pagingPosition` to `"both"` +- **THEN** Studio Pro shows a warning on the `pagingPosition` property explaining that custom pagination renders once, below the grid, and suggesting a single position instead diff --git a/packages/pluggableWidgets/datagrid-web/openspec/changes/pagination-position-not-honored/tasks.md b/packages/pluggableWidgets/datagrid-web/openspec/changes/pagination-position-not-honored/tasks.md new file mode 100644 index 0000000000..4b469f6589 --- /dev/null +++ b/packages/pluggableWidgets/datagrid-web/openspec/changes/pagination-position-not-honored/tasks.md @@ -0,0 +1,21 @@ +## 1. Runtime placement + +- [x] 1.1 `WidgetFooter.tsx`: gate the existing `` custom pagination block on `pgConfig.pagingPosition !== "top"`. +- [x] 1.2 `WidgetTopBar.tsx`: add a custom pagination branch that renders `customPagination.get()` when `pgConfig.customPaginationEnabled && pgConfig.pagingPosition === "top"` (needs `useCustomPagination` from `../model/hooks/injection-hooks`, not currently imported there). +- [x] 1.3 Unit tests for `WidgetFooter`/`WidgetTopBar` (or their existing test files) covering `pagingPosition` × `useCustomPagination` for `"top"`, `"bottom"`, `"both"`, and custom pagination disabled. + +## 2. Editor preview + +- [x] 2.1 `Datagrid.editorPreview.tsx`: add a `usePagingTopCustom`/equivalent check (or extend `usePagingTop`) so the top bar's preview renders `` when `useCustomPagination && pagingPosition === "top"`. +- [x] 2.2 `Datagrid.editorPreview.tsx`: change the footer's `useCustomPagination()` check so it excludes `pagingPosition === "top"` (footer renders custom pagination for `"bottom"` and `"both"` only). +- [x] 2.3 ~~Update/add preview snapshot or structure tests~~ — not feasible: `Datagrid.editorPreview.tsx` imports `mendix/preview/Selectable`, which has no jest moduleNameMapper stub anywhere in this repo (confirmed repo-wide: no `*-web` package unit-tests its `editorPreview.tsx`). Adding one would mean changing the shared `@mendix/pluggable-widgets-tools` jest preset, out of scope for this fix. Verified instead by code inspection (mirrors the already-tested `WidgetTopBar`/`WidgetFooter` runtime logic 1:1) plus manual Studio Pro QA. + +## 3. Studio Pro properties panel + +- [x] 3.1 `Datagrid.editorConfig.ts`: in the `useCustomPagination` branch (inside `pagination === "buttons"`), stop hiding `pagingPosition` — only hide `showPagingButtons`. +- [x] 3.2 Add a `checkCustomPaginationPosition` (or similarly named) check to `consistency-check.ts`: emit a `"warning"` on property `pagingPosition` when `values.useCustomPagination && values.pagingPosition === "both"`, wired into `check()` alongside the existing selection/column checks. +- [x] 3.3 Unit test for the new consistency-check warning (present for custom+both, absent for custom+top/bottom and for non-custom pagination). + +## 4. Docs + +- [x] 4.1 Add a `CHANGELOG.md` entry: custom pagination now respects "Position of pagination" (top/bottom/both, with "both" rendering once below the grid). From 4d46f34f9feb9b6b002ab5033795a5e374ea85f4 Mon Sep 17 00:00:00 2001 From: Yordan Stoyanov Date: Thu, 10 Sep 2026 15:22:22 +0200 Subject: [PATCH 2/5] fix(datagrid-web): honor Position of pagination for custom pagination WidgetFooter rendered custom pagination widgets unconditionally and WidgetTopBar never rendered them at all. Both now gate on pagingPosition, mirroring the built-in Pagination control; "both" renders once, in the footer, to avoid duplicating widget instances/DOM ids/state. --- .../src/components/WidgetFooter.tsx | 4 +- .../src/components/WidgetTopBar.tsx | 6 ++- .../__tests__/WidgetFooter.spec.tsx | 41 +++++++++++++++++++ .../__tests__/WidgetTopBar.spec.tsx | 41 +++++++++++++++++++ 4 files changed, 90 insertions(+), 2 deletions(-) create mode 100644 packages/pluggableWidgets/datagrid-web/src/components/__tests__/WidgetFooter.spec.tsx create mode 100644 packages/pluggableWidgets/datagrid-web/src/components/__tests__/WidgetTopBar.spec.tsx diff --git a/packages/pluggableWidgets/datagrid-web/src/components/WidgetFooter.tsx b/packages/pluggableWidgets/datagrid-web/src/components/WidgetFooter.tsx index a58930e18a..a4c9d7b5de 100644 --- a/packages/pluggableWidgets/datagrid-web/src/components/WidgetFooter.tsx +++ b/packages/pluggableWidgets/datagrid-web/src/components/WidgetFooter.tsx @@ -46,7 +46,9 @@ export const WidgetFooter = observer(function WidgetFooter(): ReactElement | nul - {customPagination.get()} + + {customPagination.get()} + diff --git a/packages/pluggableWidgets/datagrid-web/src/components/WidgetTopBar.tsx b/packages/pluggableWidgets/datagrid-web/src/components/WidgetTopBar.tsx index 2ec45e8685..666c741ee6 100644 --- a/packages/pluggableWidgets/datagrid-web/src/components/WidgetTopBar.tsx +++ b/packages/pluggableWidgets/datagrid-web/src/components/WidgetTopBar.tsx @@ -4,11 +4,12 @@ import { If } from "@mendix/widget-plugin-component-kit/If"; import { Pagination } from "./Pagination"; import { useSelectionCounterViewModel } from "../features/selection-counter/injection-hooks"; import { SelectionCounter } from "../features/selection-counter/SelectionCounter"; -import { usePaginationConfig } from "../model/hooks/injection-hooks"; +import { useCustomPagination, usePaginationConfig } from "../model/hooks/injection-hooks"; export const WidgetTopBar = observer(function WidgetTopBar(): ReactElement { const pgConfig = usePaginationConfig(); const selectionCounter = useSelectionCounterViewModel(); + const customPagination = useCustomPagination(); return (
@@ -22,6 +23,9 @@ export const WidgetTopBar = observer(function WidgetTopBar(): ReactElement { + + {customPagination.get()} +
diff --git a/packages/pluggableWidgets/datagrid-web/src/components/__tests__/WidgetFooter.spec.tsx b/packages/pluggableWidgets/datagrid-web/src/components/__tests__/WidgetFooter.spec.tsx new file mode 100644 index 0000000000..868e613500 --- /dev/null +++ b/packages/pluggableWidgets/datagrid-web/src/components/__tests__/WidgetFooter.spec.tsx @@ -0,0 +1,41 @@ +import { render, screen } from "@testing-library/react"; +import { ContainerProvider } from "brandi-react"; +import { setupIntersectionObserverStub } from "@mendix/widget-plugin-test-utils"; +import { createDatagridContainer } from "../../model/containers/createDatagridContainer"; +import { mockContainerProps } from "../../utils/test-utils"; +import { PagingPositionEnum } from "../../../typings/DatagridProps"; +import { WidgetFooter } from "../WidgetFooter"; + +setupIntersectionObserverStub(); + +function renderFooter(pagingPosition: PagingPositionEnum): void { + const [container] = createDatagridContainer( + mockContainerProps({ + useCustomPagination: true, + customPagination:
Custom pagination widgets
, + pagingPosition + }) + ); + render( + + + + ); +} + +describe("WidgetFooter custom pagination", () => { + it("renders custom pagination when position is bottom", () => { + renderFooter("bottom"); + expect(screen.getByText("Custom pagination widgets")).toBeInTheDocument(); + }); + + it("renders custom pagination when position is both", () => { + renderFooter("both"); + expect(screen.getByText("Custom pagination widgets")).toBeInTheDocument(); + }); + + it("does not render custom pagination when position is top", () => { + renderFooter("top"); + expect(screen.queryByText("Custom pagination widgets")).not.toBeInTheDocument(); + }); +}); diff --git a/packages/pluggableWidgets/datagrid-web/src/components/__tests__/WidgetTopBar.spec.tsx b/packages/pluggableWidgets/datagrid-web/src/components/__tests__/WidgetTopBar.spec.tsx new file mode 100644 index 0000000000..214b43b3f7 --- /dev/null +++ b/packages/pluggableWidgets/datagrid-web/src/components/__tests__/WidgetTopBar.spec.tsx @@ -0,0 +1,41 @@ +import { render, screen } from "@testing-library/react"; +import { ContainerProvider } from "brandi-react"; +import { setupIntersectionObserverStub } from "@mendix/widget-plugin-test-utils"; +import { createDatagridContainer } from "../../model/containers/createDatagridContainer"; +import { mockContainerProps } from "../../utils/test-utils"; +import { PagingPositionEnum } from "../../../typings/DatagridProps"; +import { WidgetTopBar } from "../WidgetTopBar"; + +setupIntersectionObserverStub(); + +function renderTopBar(pagingPosition: PagingPositionEnum): void { + const [container] = createDatagridContainer( + mockContainerProps({ + useCustomPagination: true, + customPagination:
Custom pagination widgets
, + pagingPosition + }) + ); + render( + + + + ); +} + +describe("WidgetTopBar custom pagination", () => { + it("renders custom pagination when position is top", () => { + renderTopBar("top"); + expect(screen.getByText("Custom pagination widgets")).toBeInTheDocument(); + }); + + it("does not render custom pagination when position is bottom", () => { + renderTopBar("bottom"); + expect(screen.queryByText("Custom pagination widgets")).not.toBeInTheDocument(); + }); + + it("does not render custom pagination when position is both (renders once, in the footer)", () => { + renderTopBar("both"); + expect(screen.queryByText("Custom pagination widgets")).not.toBeInTheDocument(); + }); +}); From 1883a2057bec25be7f298cb55bed5a5eddc69cd1 Mon Sep 17 00:00:00 2001 From: Yordan Stoyanov Date: Thu, 10 Sep 2026 15:22:24 +0200 Subject: [PATCH 3/5] fix(datagrid-web): match editor preview to custom pagination placement Preview always rendered custom pagination in the footer. Split the single useCustomPagination() check into top/bottom variants so the page editor agrees with runtime for every Position of pagination value. --- .../datagrid-web/src/Datagrid.editorPreview.tsx | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/packages/pluggableWidgets/datagrid-web/src/Datagrid.editorPreview.tsx b/packages/pluggableWidgets/datagrid-web/src/Datagrid.editorPreview.tsx index 4a0a0a5743..5b01ef232a 100644 --- a/packages/pluggableWidgets/datagrid-web/src/Datagrid.editorPreview.tsx +++ b/packages/pluggableWidgets/datagrid-web/src/Datagrid.editorPreview.tsx @@ -105,7 +105,10 @@ function WidgetTopBar(): ReactElement {
{useTopCounter() ? : null}
-
{usePagingTop() ? : null}
+
+ {usePagingTop() ? : null} + {useCustomPaginationTop() ? : null} +
); @@ -139,7 +142,7 @@ function WidgetFooter(): ReactElement {
{usePagingBot() ? : null} - {useCustomPagination() ? : null} + {useCustomPaginationBottom() ? : null}
@@ -403,7 +406,12 @@ function usePagingBot(): boolean { return visible && props.pagingPosition !== "top"; } -function useCustomPagination(): boolean { +function useCustomPaginationTop(): boolean { + const props = useProps(); + return props.useCustomPagination && props.pagingPosition === "top"; +} + +function useCustomPaginationBottom(): boolean { const props = useProps(); - return props.useCustomPagination; + return props.useCustomPagination && props.pagingPosition !== "top"; } From a2a2cc5d284cf31ba4624373fa116f354e06b5d1 Mon Sep 17 00:00:00 2001 From: Yordan Stoyanov Date: Thu, 10 Sep 2026 15:22:25 +0200 Subject: [PATCH 4/5] fix(datagrid-web): keep Position of pagination visible for custom pagination pagingPosition was hidden from the properties panel whenever custom pagination was enabled, a stopgap from when the property had no effect. Now that it does, keep it visible and warn when it's set to "Both" with custom pagination, since that combination renders once, below the grid. --- .../datagrid-web/src/Datagrid.editorConfig.ts | 2 +- .../consistency-check.spec.ts.snap | 10 ++++ .../src/__tests__/consistency-check.spec.ts | 50 +++++++++++++++++++ .../datagrid-web/src/consistency-check.ts | 17 +++++++ 4 files changed, 78 insertions(+), 1 deletion(-) diff --git a/packages/pluggableWidgets/datagrid-web/src/Datagrid.editorConfig.ts b/packages/pluggableWidgets/datagrid-web/src/Datagrid.editorConfig.ts index 0db6fb4b60..f187c68fb4 100644 --- a/packages/pluggableWidgets/datagrid-web/src/Datagrid.editorConfig.ts +++ b/packages/pluggableWidgets/datagrid-web/src/Datagrid.editorConfig.ts @@ -80,7 +80,7 @@ export function getProperties(values: DatagridPreviewProps, defaultProperties: P if (values.useCustomPagination === false) { hidePropertyIn(defaultProperties, values, "customPagination"); } else { - hidePropertiesIn(defaultProperties, values, ["pagingPosition", "showPagingButtons"]); + hidePropertyIn(defaultProperties, values, "showPagingButtons"); } } else { hidePropertyIn(defaultProperties, values, "showPagingButtons"); diff --git a/packages/pluggableWidgets/datagrid-web/src/__tests__/__snapshots__/consistency-check.spec.ts.snap b/packages/pluggableWidgets/datagrid-web/src/__tests__/__snapshots__/consistency-check.spec.ts.snap index 50e447d262..b3cee4a735 100644 --- a/packages/pluggableWidgets/datagrid-web/src/__tests__/__snapshots__/consistency-check.spec.ts.snap +++ b/packages/pluggableWidgets/datagrid-web/src/__tests__/__snapshots__/consistency-check.spec.ts.snap @@ -1,5 +1,15 @@ // Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing +exports[`consistency check custom pagination position warns when custom pagination is enabled and position is both 1`] = ` +[ + { + "message": "Custom pagination cannot be shown in both positions and will render below the grid. Set "Position of pagination" to "Above grid" or "Below grid" to choose a single position.", + "property": "pagingPosition", + "severity": "warning", + }, +] +`; + exports[`consistency check returns error when row select method and action trigger overlap selection: multi by row click 1`] = ` [ { diff --git a/packages/pluggableWidgets/datagrid-web/src/__tests__/consistency-check.spec.ts b/packages/pluggableWidgets/datagrid-web/src/__tests__/consistency-check.spec.ts index ceb3eda982..08494475d0 100644 --- a/packages/pluggableWidgets/datagrid-web/src/__tests__/consistency-check.spec.ts +++ b/packages/pluggableWidgets/datagrid-web/src/__tests__/consistency-check.spec.ts @@ -75,4 +75,54 @@ describe("consistency check", () => { expect(check(props as unknown as DatagridPreviewProps)).toEqual([]); }); }); + + describe("custom pagination position", () => { + test("warns when custom pagination is enabled and position is both", () => { + const props = { + itemSelection: "None", + onClick: null, + columns: [], + useCustomPagination: true, + pagingPosition: "both" + }; + + expect(check(props as unknown as DatagridPreviewProps)).toMatchSnapshot(); + }); + + test("does not warn when custom pagination is enabled and position is top", () => { + const props = { + itemSelection: "None", + onClick: null, + columns: [], + useCustomPagination: true, + pagingPosition: "top" + }; + + expect(check(props as unknown as DatagridPreviewProps)).toEqual([]); + }); + + test("does not warn when custom pagination is enabled and position is bottom", () => { + const props = { + itemSelection: "None", + onClick: null, + columns: [], + useCustomPagination: true, + pagingPosition: "bottom" + }; + + expect(check(props as unknown as DatagridPreviewProps)).toEqual([]); + }); + + test("does not warn when position is both and custom pagination is disabled", () => { + const props = { + itemSelection: "None", + onClick: null, + columns: [], + useCustomPagination: false, + pagingPosition: "both" + }; + + expect(check(props as unknown as DatagridPreviewProps)).toEqual([]); + }); + }); }); diff --git a/packages/pluggableWidgets/datagrid-web/src/consistency-check.ts b/packages/pluggableWidgets/datagrid-web/src/consistency-check.ts index de02c76a80..2c4e7a965c 100644 --- a/packages/pluggableWidgets/datagrid-web/src/consistency-check.ts +++ b/packages/pluggableWidgets/datagrid-web/src/consistency-check.ts @@ -17,6 +17,11 @@ export function check(values: DatagridPreviewProps): Problem[] { errors.push(...checkSelectionSettings(values)); + const customPaginationPositionError = checkCustomPaginationPosition(values); + if (customPaginationPositionError) { + errors.push(customPaginationPositionError); + } + return errors; } @@ -67,6 +72,18 @@ const checkHidableSettings = ( } }; +const checkCustomPaginationPosition = (values: DatagridPreviewProps): Problem | undefined => { + if (values.useCustomPagination && values.pagingPosition === "both") { + return { + property: "pagingPosition", + severity: "warning", + message: + "Custom pagination cannot be shown in both positions and will render below the grid. " + + 'Set "Position of pagination" to "Above grid" or "Below grid" to choose a single position.' + }; + } +}; + const checkSelectionSettings = (values: DatagridPreviewProps): Problem[] => { const errors: Problem[] = []; From c0c76b38c77f1d3cdf151ccf5ece0f0e53ca9bed Mon Sep 17 00:00:00 2001 From: Yordan Stoyanov Date: Thu, 10 Sep 2026 15:22:27 +0200 Subject: [PATCH 5/5] docs(datagrid-web): add changelog for custom pagination position fix --- packages/pluggableWidgets/datagrid-web/CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/pluggableWidgets/datagrid-web/CHANGELOG.md b/packages/pluggableWidgets/datagrid-web/CHANGELOG.md index ce1b24708c..6a03a504de 100644 --- a/packages/pluggableWidgets/datagrid-web/CHANGELOG.md +++ b/packages/pluggableWidgets/datagrid-web/CHANGELOG.md @@ -9,6 +9,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), ### Fixed - We fixed an issue where the top bar did not stack its content vertically in narrow containers. +- We fixed an issue where custom pagination ignored "Position of pagination" and always rendered below the grid. It now renders above the grid, below the grid, or — for "Both" — once, below the grid. ### Added