Skip to content

Commit 2cc655b

Browse files
authored
Merge pull request #8116 from oguhpereira/feat/add-custom-filter-in-useList
Add a custom filter property in useList
2 parents 50abbf8 + ce15352 commit 2cc655b

File tree

3 files changed

+74
-16
lines changed

3 files changed

+74
-16
lines changed

docs/useList.md

+18
Original file line numberDiff line numberDiff line change
@@ -242,3 +242,21 @@ const {
242242
refetch, // a function that throws an error, as refetch doesn't make sense for local data
243243
} = getGetList({ data });
244244
```
245+
## `filterCallback`
246+
247+
Property for custom filter definition. Being able to apply more complex filters using operators
248+
249+
```jsx
250+
const { data } = useList({
251+
data: [
252+
{ id: 1, name: 'Arnold' },
253+
{ id: 2, name: 'Sylvester' },
254+
{ id: 3, name: 'Jean-Claude' },
255+
],
256+
sort: { field: 'name', order: 'ASC' },
257+
filterCallback: (record) => record.id > 1 && record.name !== 'Jean-Claude'
258+
});
259+
// data will be
260+
// [
261+
// { id: 2, name: 'Sylvester' },
262+
// ]

packages/ra-core/src/controller/list/useList.spec.tsx

+35
Original file line numberDiff line numberDiff line change
@@ -228,4 +228,39 @@ describe('<useList />', () => {
228228
})
229229
);
230230
});
231+
232+
it('should filter array data based on the custom filter', async () => {
233+
const callback = jest.fn();
234+
const data = [
235+
{ id: 1, items: ['one', 'two'] },
236+
{ id: 2, items: ['three'] },
237+
{ id: 3, items: 'four' },
238+
{ id: 4, items: ['five'] },
239+
];
240+
241+
render(
242+
<UseList
243+
data={data}
244+
sort={{ field: 'id', order: 'ASC' }}
245+
filterCallback={record => record.id > 2}
246+
callback={callback}
247+
/>
248+
);
249+
250+
await waitFor(() => {
251+
expect(callback).toHaveBeenCalledWith(
252+
expect.objectContaining({
253+
sort: { field: 'id', order: 'ASC' },
254+
isFetching: false,
255+
isLoading: false,
256+
data: [
257+
{ id: 3, items: 'four' },
258+
{ id: 4, items: ['five'] },
259+
],
260+
error: undefined,
261+
total: 2,
262+
})
263+
);
264+
});
265+
});
231266
});

packages/ra-core/src/controller/list/useList.ts

+21-16
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ const refetch = () => {
4848
* @param {Number} props.page: Optional. The initial page index
4949
* @param {Number} props.perPage: Optional. The initial page size
5050
* @param {SortPayload} props.sort: Optional. The initial sort (field and order)
51+
* @param {filterCallback} prop.filterCallback Optional. A function that allows you to make a custom filter
5152
*/
5253
export const useList = <RecordType extends RaRecord = any>(
5354
props: UseListOptions<RecordType>
@@ -61,6 +62,7 @@ export const useList = <RecordType extends RaRecord = any>(
6162
page: initialPage = 1,
6263
perPage: initialPerPage = 1000,
6364
sort: initialSort,
65+
filterCallback = (record: RecordType) => Boolean(record),
6466
} = props;
6567
const resource = useResourceContext(props);
6668

@@ -161,23 +163,25 @@ export const useList = <RecordType extends RaRecord = any>(
161163

162164
// 1. filter
163165
if (filterValues) {
164-
tempData = data.filter(record =>
165-
Object.entries(filterValues).every(
166-
([filterName, filterValue]) => {
167-
const recordValue = get(record, filterName);
168-
const result = Array.isArray(recordValue)
169-
? Array.isArray(filterValue)
170-
? recordValue.some(item =>
171-
filterValue.includes(item)
172-
)
173-
: recordValue.includes(filterValue)
174-
: Array.isArray(filterValue)
175-
? filterValue.includes(recordValue)
176-
: filterValue == recordValue; // eslint-disable-line eqeqeq
177-
return result;
178-
}
166+
tempData = data
167+
.filter(record =>
168+
Object.entries(filterValues).every(
169+
([filterName, filterValue]) => {
170+
const recordValue = get(record, filterName);
171+
const result = Array.isArray(recordValue)
172+
? Array.isArray(filterValue)
173+
? recordValue.some(item =>
174+
filterValue.includes(item)
175+
)
176+
: recordValue.includes(filterValue)
177+
: Array.isArray(filterValue)
178+
? filterValue.includes(recordValue)
179+
: filterValue == recordValue; // eslint-disable-line eqeqeq
180+
return result;
181+
}
182+
)
179183
)
180-
);
184+
.filter(filterCallback);
181185
}
182186
const filteredLength = tempData.length;
183187

@@ -269,6 +273,7 @@ export interface UseListOptions<RecordType extends RaRecord = any> {
269273
perPage?: number;
270274
sort?: SortPayload;
271275
resource?: string;
276+
filterCallback?: (record: RecordType) => boolean;
272277
}
273278

274279
export type UseListValue<

0 commit comments

Comments
 (0)