Skip to content

Commit 3bb860f

Browse files
authored
feat(sort order override): add override to control sort order asc desc (#22)
* chore: ignore node modules and vscode files * chore: update package lock file * feat(sort order override): add override to control sort order asc desc * chore: use shorthand syntax for fragment
1 parent 9520df8 commit 3bb860f

5 files changed

Lines changed: 78 additions & 8 deletions

File tree

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,4 @@
11
dist
22
coverage
3+
node_modules
4+
.vscode

package-lock.json

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/hooks.tsx

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -99,9 +99,15 @@ const createReducer = <T extends DataType>() => (
9999
const columnCopy = state.columns.map(column => {
100100
// if the row was found
101101
if (action.columnName === column.name) {
102-
// if it's undefined, start by setting to ascending, otherwise toggle
103-
isAscending =
104-
column.sorted.asc === undefined ? true : !column.sorted.asc;
102+
if (action.isAscOverride !== undefined) {
103+
// force the sort order
104+
isAscending = action.isAscOverride;
105+
} else {
106+
// if it's undefined, start by setting to ascending, otherwise toggle
107+
isAscending =
108+
column.sorted.asc === undefined ? true : !column.sorted.asc;
109+
}
110+
105111
if (column.sort) {
106112
sortedRows = isAscending
107113
? state.rows.sort(column.sort)
@@ -343,8 +349,8 @@ export const useTable = <T extends DataType>(
343349
dispatch,
344350
selectRow: (rowId: number) => dispatch({ type: 'SELECT_ROW', rowId }),
345351
toggleAll: () => dispatch({ type: 'TOGGLE_ALL' }),
346-
toggleSort: (columnName: string) =>
347-
dispatch({ type: 'TOGGLE_SORT', columnName }),
352+
toggleSort: (columnName: string, isAscOverride?: boolean) =>
353+
dispatch({ type: 'TOGGLE_SORT', columnName, isAscOverride }),
348354
setSearchString: (searchString: string) =>
349355
dispatch({ type: 'SEARCH_STRING', searchString }),
350356
pagination: state.pagination,

src/test/sorting.spec.tsx

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,24 @@ const Table = <T extends {}>({
5252
))}
5353
</tbody>
5454
</table>
55+
{headers.map((header, idx) => (
56+
<>
57+
<button
58+
key={idx}
59+
data-testid={`toggle-sort-asc-cta-${header.name}`}
60+
onClick={() => toggleSort(header.name, true)}
61+
>
62+
Sort Asc
63+
</button>
64+
<button
65+
key={idx}
66+
data-testid={`toggle-sort-desc-cta-${header.name}`}
67+
onClick={() => toggleSort(header.name, false)}
68+
>
69+
Sort Desc
70+
</button>
71+
</>
72+
))}
5573
<button
5674
data-testid="add-row"
5775
onClick={() =>
@@ -128,6 +146,50 @@ test('Should render a table and preserve sorting when data changes', () => {
128146
// expect(screen.queryAllByRole('table-row')).toHaveLength(12);
129147
});
130148

149+
test('Should override sort order', () => {
150+
const { columns, data } = makeSimpleData<{
151+
firstName: string;
152+
lastName: string;
153+
birthDate: string;
154+
}>();
155+
156+
const dataToSortDesc = [...data];
157+
dataToSortDesc[1].firstName = 'Zippy';
158+
159+
render(<Table columns={columns} data={dataToSortDesc} />);
160+
161+
const sortFirstNameDescCta = screen.getByTestId(
162+
'toggle-sort-desc-cta-firstName'
163+
);
164+
const sortFirstNameAscCta = screen.getByTestId(
165+
'toggle-sort-asc-cta-firstName'
166+
);
167+
168+
// should be sorted in descending order
169+
fireEvent.click(sortFirstNameDescCta);
170+
let firstRow = screen.getByTestId('row-0');
171+
let { getByText } = within(firstRow);
172+
expect(getByText('Zippy')).toBeInTheDocument();
173+
174+
// should (still) be sorted in descending order
175+
fireEvent.click(sortFirstNameDescCta);
176+
firstRow = screen.getByTestId('row-0');
177+
({ getByText } = within(firstRow));
178+
expect(getByText('Zippy')).toBeInTheDocument();
179+
180+
// should be sorted in ascending order
181+
fireEvent.click(sortFirstNameAscCta);
182+
firstRow = screen.getByTestId('row-0');
183+
({ getByText } = within(firstRow));
184+
expect(getByText('Bilbo')).toBeInTheDocument();
185+
186+
// should (still) be sorted in ascending order
187+
fireEvent.click(sortFirstNameAscCta);
188+
firstRow = screen.getByTestId('row-0');
189+
({ getByText } = within(firstRow));
190+
expect(getByText('Bilbo')).toBeInTheDocument();
191+
});
192+
131193
test('Should sort by dates correctly', () => {
132194
const { columns, data } = makeSimpleData<{
133195
firstName: string;

src/types.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ export interface UseTableReturnType<T> {
102102
rows: RowType<T>[];
103103
selectedRows: RowType<T>[];
104104
dispatch: React.Dispatch<TableAction<T>>;
105-
toggleSort: (columnName: string) => void;
105+
toggleSort: (columnName: string, isAscOverride?: boolean) => void;
106106
selectRow: (id: number) => void;
107107
toggleAll: () => void;
108108
setSearchString: (searchString: string) => void;
@@ -133,7 +133,7 @@ export type TableState<T extends DataType> = {
133133
};
134134

135135
export type TableAction<T extends DataType> =
136-
| { type: 'TOGGLE_SORT'; columnName: string }
136+
| { type: 'TOGGLE_SORT'; columnName: string; isAscOverride?: boolean }
137137
| { type: 'SELECT_ROW'; rowId: number }
138138
| { type: 'GLOBAL_FILTER'; filter: (row: RowType<T>[]) => RowType<T>[] }
139139
| { type: 'SEARCH_STRING'; searchString: string }

0 commit comments

Comments
 (0)