Skip to content

Commit 53c82d9

Browse files
Fix Paging inside Form / Allow custom nodes (#76)
when inside form the paging tends to flex along the whole container. This behavior has been fixed. Also, allows custom nodes for back/next first/last page (default texts preserved)
1 parent c678235 commit 53c82d9

4 files changed

Lines changed: 87 additions & 7 deletions

File tree

CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
### Fix
11+
12+
- paging when displayed inside a form.
13+
14+
### Added
15+
16+
- possibility to customize back/next first/last page navigation components.
17+
1018
### Removed
1119

1220
- remove cypress declarations

cypress/cypress/component/Paging/Paging.cy.tsx

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,4 +100,59 @@ describe("Paging.cy.tsx", () => {
100100
.replace("{total}", (pages * itemsPerPage).toString()),
101101
);
102102
});
103+
104+
it("custom navigationComponents work correctly", () => {
105+
const itemsPerPage = 10;
106+
const pages = 5;
107+
const currentPage = 3;
108+
const translations = { showedItemsText: "Item {from} to {to} from {total}", itemsPerPageDropdown: "Items per page" };
109+
const customNavigationComponents = {
110+
backPageComponent: "←",
111+
nextPageComponent: "→",
112+
firstPageComponent: "⇤",
113+
lastPageComponent: "⇥",
114+
};
115+
116+
mount(
117+
<Paging
118+
currentItemsPerPage={itemsPerPage}
119+
currentPage={currentPage}
120+
currentRecordCount={itemsPerPage}
121+
setCurrentPage={cy.spy().as("setCurrentPage")}
122+
totalRecords={pages * itemsPerPage}
123+
setItemsPerPage={cy.spy().as("setItemsPerPage")}
124+
translations={translations}
125+
navigationComponents={customNavigationComponents}
126+
/>,
127+
);
128+
129+
// Check that custom navigation components are rendered
130+
cy.get("[data-cy-root] > .container-fluid > .row > .col-6:nth-of-type(2) > .btn-group > button.btn").then(
131+
(items: JQuery<HTMLElement>) => {
132+
// Verify custom symbols are present
133+
cy.wrap(items.filter((_, item) => item.textContent === "⇤"))
134+
.should("exist")
135+
.and("be.visible");
136+
cy.wrap(items.filter((_, item) => item.textContent === "←"))
137+
.should("exist")
138+
.and("be.visible");
139+
cy.wrap(items.filter((_, item) => item.textContent === "→"))
140+
.should("exist")
141+
.and("be.visible");
142+
cy.wrap(items.filter((_, item) => item.textContent === "⇥"))
143+
.should("exist")
144+
.and("be.visible");
145+
146+
// Test functionality with custom components
147+
cy.wrap(items.filter((_, item) => item.textContent === "⇤")).click();
148+
cy.get("@setCurrentPage").should("be.calledWith", 1);
149+
cy.wrap(items.filter((_, item) => item.textContent === "←")).click();
150+
cy.get("@setCurrentPage").should("be.calledWith", currentPage - 1);
151+
cy.wrap(items.filter((_, item) => item.textContent === "→")).click();
152+
cy.get("@setCurrentPage").should("be.calledWith", currentPage + 1);
153+
cy.wrap(items.filter((_, item) => item.textContent === "⇥")).click();
154+
cy.get("@setCurrentPage").should("be.calledWith", pages);
155+
},
156+
);
157+
});
103158
});

src/lib/Paging/Paging.tsx

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { Button, ButtonGroup, Col, DropdownItem, DropdownMenu, DropdownToggle, Row, UncontrolledButtonDropdown } from "reactstrap";
2-
import { useMemo } from "react";
2+
import { ReactNode, useMemo } from "react";
33

44
interface PagingProps {
55
currentItemsPerPage: number;
@@ -8,6 +8,7 @@ interface PagingProps {
88
currentRecordCount: number;
99
pagingPossible?: boolean;
1010
translations: PagingTranslations;
11+
navigationComponents?: PagingNavigationComponents;
1112
possiblePageItemCounts?: number[];
1213
maxPagesShown?: number;
1314
showControls?: boolean;
@@ -21,6 +22,20 @@ interface PagingTranslations {
2122
itemsPerPageDropdown: string;
2223
}
2324

25+
interface PagingNavigationComponents {
26+
backPageComponent: ReactNode;
27+
nextPageComponent: ReactNode;
28+
firstPageComponent: ReactNode;
29+
lastPageComponent: ReactNode;
30+
}
31+
32+
const defaultNavigationComponents: PagingNavigationComponents = {
33+
backPageComponent: "<",
34+
nextPageComponent: ">",
35+
firstPageComponent: "<<",
36+
lastPageComponent: ">>",
37+
};
38+
2439
// eslint-disable-next-line complexity
2540
const Paging = ({
2641
currentItemsPerPage,
@@ -29,13 +44,15 @@ const Paging = ({
2944
currentRecordCount,
3045
pagingPossible = true,
3146
translations,
47+
navigationComponents = defaultNavigationComponents,
3248
possiblePageItemCounts,
3349
maxPagesShown = 7,
3450
showControls = true,
3551
changePageSizePossible = true,
3652
setItemsPerPage,
3753
setCurrentPage,
3854
}: PagingProps) => {
55+
const { backPageComponent, nextPageComponent, firstPageComponent, lastPageComponent } = navigationComponents;
3956
const maxPage = Math.ceil(totalRecords / currentItemsPerPage);
4057
const firstPageShown = Math.max(0, Math.min(currentPage - Math.ceil(maxPagesShown / 2), maxPage - maxPagesShown));
4158

@@ -79,12 +96,12 @@ const Paging = ({
7996
<ButtonGroup size="sm">
8097
{showControls && (
8198
<Button color="secondary" outline disabled={currentPage === 1} onClick={() => setCurrentPage(1)}>
82-
{"<<"}
99+
{firstPageComponent}
83100
</Button>
84101
)}
85102
{showControls && (
86103
<Button color="secondary" outline disabled={currentPage === 1} onClick={() => setCurrentPage(currentPage - 1)}>
87-
{"<"}
104+
{backPageComponent}
88105
</Button>
89106
)}
90107
{Array.from({ length: maxPage + 1 }, (_, i) => i)
@@ -97,12 +114,12 @@ const Paging = ({
97114
))}
98115
{showControls && (
99116
<Button color="secondary" outline disabled={currentPage === maxPage} onClick={() => setCurrentPage(currentPage + 1)}>
100-
{">"}
117+
{nextPageComponent}
101118
</Button>
102119
)}
103120
{showControls && (
104121
<Button color="secondary" outline disabled={currentPage === maxPage} onClick={() => setCurrentPage(maxPage)}>
105-
{">>"}
122+
{lastPageComponent}
106123
</Button>
107124
)}
108125
</ButtonGroup>
@@ -113,4 +130,4 @@ const Paging = ({
113130
);
114131
};
115132

116-
export { Paging, PagingProps, PagingTranslations };
133+
export { Paging, PagingProps, PagingTranslations, PagingNavigationComponents };

styles/Form/_form.scss

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
form div[role="group"] {
1+
form div[role="group"]:not(.paging div[role="group"]) {
22
display: flex;
33
gap: 0.25rem;
44

0 commit comments

Comments
 (0)