Skip to content

Commit 3048968

Browse files
authored
improved composables
1 parent b5c62df commit 3048968

File tree

2 files changed

+81
-38
lines changed

2 files changed

+81
-38
lines changed

resources/js/composables/useLazyDataTable.ts

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
import { usePaginatedData } from './usePaginatedData';
2-
import cloneDeep from 'lodash-es/cloneDeep';
32
import { DataTableFilterMetaData, DataTableFilterEvent, DataTableSortEvent } from 'primevue';
43
import { PrimeVueDataFilters } from '@/types';
54

65
export function useLazyDataTable(
7-
propDataToFetch: string,
6+
propDataToFetch: string | string[],
87
initialFilters: PrimeVueDataFilters = {},
98
initialRows: number = 20
109
) {
@@ -34,11 +33,12 @@ export function useLazyDataTable(
3433

3534
/**
3635
* "Override" parent composable function
37-
* Event driven filtering rather than reactive state
36+
* Event-driven filtering rather than reactive state
3837
*/
3938
function filter(event: DataTableFilterEvent) {
4039
pagination.value.page = 1;
4140
const newFilters: PrimeVueDataFilters = {};
41+
4242
Object.entries(event.filters).forEach(([key, rawFilter]) => {
4343
if (
4444
rawFilter &&
@@ -48,19 +48,26 @@ export function useLazyDataTable(
4848
newFilters[key] = rawFilter as DataTableFilterMetaData;
4949
}
5050
});
51+
5152
filters.value = newFilters;
5253
parseEventFilterValues();
53-
fetchData().then(() => {
54-
scrollToTop();
54+
55+
fetchData({
56+
onFinish: () => {
57+
scrollToTop();
58+
},
5559
});
5660
}
5761

5862
function sort(event: DataTableSortEvent) {
5963
pagination.value.page = 1;
6064
sorting.value.field = event.sortField ? String(event.sortField) : '';
6165
sorting.value.order = event.sortOrder || 1;
62-
fetchData().then(() => {
63-
scrollToTop();
66+
67+
fetchData({
68+
onFinish: () => {
69+
scrollToTop();
70+
},
6471
});
6572
}
6673

@@ -69,15 +76,22 @@ export function useLazyDataTable(
6976
* usePaginatedData() resets sorting.value state as a new object, this will not work for DataTable's
7077
*/
7178
function reset() {
72-
const defaultFilters = cloneDeep(initialFilters);
79+
const defaultFilters = structuredClone(initialFilters);
80+
7381
Object.keys(defaultFilters).forEach((key) => {
7482
filters.value[key].value = defaultFilters[key].value;
7583
});
84+
7685
sorting.value.field = '';
7786
sorting.value.order = 1;
7887
pagination.value.page = 1;
7988
pagination.value.rows = initialRows;
80-
fetchData();
89+
90+
fetchData({
91+
onFinish: () => {
92+
scrollToTop();
93+
},
94+
});
8195
}
8296

8397
return {
@@ -95,4 +109,4 @@ export function useLazyDataTable(
95109
reset,
96110
hardReset,
97111
};
98-
}
112+
}

resources/js/composables/usePaginatedData.ts

Lines changed: 57 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ import { ref, computed, onMounted } from 'vue';
22
import { router } from '@inertiajs/vue3';
33
import { FilterMatchMode } from '@primevue/core/api';
44
import debounce from 'lodash-es/debounce';
5-
import cloneDeep from 'lodash-es/cloneDeep';
65
import { PageState, DataTablePageEvent } from 'primevue';
76
import { PrimeVueDataFilters } from '@/types';
87
import qs from 'qs';
@@ -24,13 +23,13 @@ interface SortState {
2423
}
2524

2625
export function usePaginatedData(
27-
propDataToFetch: string,
26+
propDataToFetch: string | string[],
2827
initialFilters: PrimeVueDataFilters = {},
2928
initialRows: number = 20
3029
) {
3130
const urlParams = ref<PaginatedFilteredSortedQueryParams>({});
3231
const processing = ref<boolean>(false);
33-
const filters = ref<PrimeVueDataFilters>(cloneDeep(initialFilters));
32+
const filters = ref<PrimeVueDataFilters>(structuredClone(initialFilters));
3433
const sorting = ref<SortState>({
3534
field: '',
3635
order: 1,
@@ -44,9 +43,9 @@ export function usePaginatedData(
4443
return (pagination.value.page - 1) * pagination.value.rows;
4544
});
4645
const filteredOrSorted = computed(() => {
47-
const filters = urlParams.value?.filters || {};
46+
const paramsFilters = urlParams.value?.filters || {};
4847
const sortField = urlParams.value?.sortField || null;
49-
const isFiltering = Object.values(filters).some(
48+
const isFiltering = Object.values(paramsFilters).some(
5049
(filter) => filter.value !== null && filter.value !== ''
5150
);
5251
const isSorting = sortField !== null && sortField !== '';
@@ -64,11 +63,11 @@ export function usePaginatedData(
6463
ignoreQueryPrefix: true,
6564
strictNullHandling: true,
6665
decoder: function (str, defaultDecoder) {
67-
// set empty string values to null
6866
const value = defaultDecoder(str);
6967
return value === '' ? null : value;
7068
},
7169
}) as PaginatedFilteredSortedQueryParams;
70+
7271
urlParams.value = { ...params };
7372
}
7473

@@ -79,9 +78,16 @@ export function usePaginatedData(
7978
});
8079
}
8180

82-
function fetchData() {
81+
function fetchData(options: {
82+
onSuccess?: (page: any) => void;
83+
onError?: (errors: any) => void;
84+
onFinish?: () => void;
85+
} = {}) {
86+
const { onSuccess: successCallback, onError: errorCallback, onFinish: finishCallback } = options;
87+
8388
return new Promise((resolve, reject) => {
8489
processing.value = true;
90+
8591
router.visit(window.location.pathname, {
8692
method: 'get',
8793
data: {
@@ -94,28 +100,42 @@ export function usePaginatedData(
94100
preserveUrl: false,
95101
showProgress: true,
96102
replace: true,
97-
only: [propDataToFetch],
103+
only: Array.isArray(propDataToFetch) ? propDataToFetch : [propDataToFetch],
98104
onSuccess: (page) => {
105+
if (typeof successCallback === 'function') {
106+
successCallback(page);
107+
}
108+
99109
resolve(page);
100110
},
101111
onError: (errors) => {
112+
if (typeof errorCallback === 'function') {
113+
errorCallback(errors);
114+
}
115+
102116
reject(errors);
103117
},
104118
onFinish: () => {
105119
setUrlParams();
106120
processing.value = false;
121+
122+
if (typeof finishCallback === 'function') {
123+
finishCallback();
124+
}
107125
},
108126
});
109127
});
110128
}
111129

112130
function paginate(event: PageState | DataTablePageEvent) {
113-
if (event.rows != pagination.value.rows) {
131+
if (event.rows !== pagination.value.rows) {
114132
pagination.value.page = 1;
115133
} else {
116134
pagination.value.page = event.page + 1;
117135
}
136+
118137
pagination.value.rows = event.rows;
138+
119139
fetchData().then(() => {
120140
scrollToTop();
121141
});
@@ -129,19 +149,23 @@ export function usePaginatedData(
129149
}
130150

131151
function reset() {
132-
const defaultFilters = cloneDeep(initialFilters);
152+
const defaultFilters = structuredClone(initialFilters);
153+
133154
Object.keys(defaultFilters).forEach((key) => {
134155
filters.value[key].value = defaultFilters[key].value;
135156
filters.value[key].matchMode = defaultFilters[key].matchMode;
136157
});
158+
137159
sorting.value = {
138160
field: '',
139161
order: 1,
140162
};
163+
141164
pagination.value = {
142165
page: 1,
143166
rows: initialRows,
144167
};
168+
145169
fetchData();
146170
}
147171

@@ -151,23 +175,25 @@ export function usePaginatedData(
151175
preserveUrl: false,
152176
showProgress: true,
153177
replace: true,
154-
only: [propDataToFetch],
178+
only: Array.isArray(propDataToFetch) ? propDataToFetch : [propDataToFetch],
155179
});
156180
}
157181

158182
function parseUrlFilterValues() {
159183
Object.keys(filters.value).forEach((key) => {
160184
const filter = filters.value[key];
185+
161186
if (!filter?.value || !filter?.matchMode) {
162187
return;
163188
}
189+
164190
if (
165191
filter.matchMode == FilterMatchMode.DATE_IS ||
166192
filter.matchMode == FilterMatchMode.DATE_IS_NOT ||
167193
filter.matchMode == FilterMatchMode.DATE_BEFORE ||
168194
filter.matchMode == FilterMatchMode.DATE_AFTER
169195
) {
170-
filters.value[key].value = new Date(filter.value);
196+
filters.value[key].value = new Date(filter.value as string);
171197
} else if (filter.matchMode == FilterMatchMode.BETWEEN) {
172198
filter.value.forEach((value: any, index: number) => {
173199
if (typeof value === 'string') {
@@ -190,12 +216,10 @@ export function usePaginatedData(
190216
} else {
191217
// Unique array values
192218
const unique = [...new Set(filter.value)];
219+
193220
filter.value = unique;
194221
filter.value.forEach((value: any, index: number) => {
195-
if (
196-
typeof value === 'string' &&
197-
!isNaN(Number(value))
198-
) {
222+
if (typeof value === 'string' && !isNaN(Number(value))) {
199223
filter.value[index] = Number(value);
200224
}
201225
});
@@ -204,23 +228,28 @@ export function usePaginatedData(
204228
});
205229
}
206230

207-
function parseUrlParams(urlParams: PaginatedFilteredSortedQueryParams) {
231+
function parseUrlParams(urlParamsObj: PaginatedFilteredSortedQueryParams) {
208232
filters.value = {
209-
...cloneDeep(initialFilters),
210-
...urlParams?.filters,
233+
...structuredClone(initialFilters),
234+
...urlParamsObj?.filters,
211235
};
236+
212237
parseUrlFilterValues();
213-
if (urlParams?.sortField) {
214-
sorting.value.field = urlParams.sortField;
238+
239+
if (urlParamsObj?.sortField) {
240+
sorting.value.field = urlParamsObj.sortField;
215241
}
216-
if (urlParams?.sortOrder) {
217-
sorting.value.order = parseInt(urlParams.sortOrder);
242+
243+
if (urlParamsObj?.sortOrder) {
244+
sorting.value.order = parseInt(urlParamsObj.sortOrder);
218245
}
219-
if (urlParams?.page) {
220-
pagination.value.page = parseInt(urlParams.page);
246+
247+
if (urlParamsObj?.page) {
248+
pagination.value.page = parseInt(urlParamsObj.page);
221249
}
222-
if (urlParams?.rows) {
223-
pagination.value.rows = parseInt(urlParams.rows);
250+
251+
if (urlParamsObj?.rows) {
252+
pagination.value.rows = parseInt(urlParamsObj.rows);
224253
}
225254
}
226255

@@ -245,4 +274,4 @@ export function usePaginatedData(
245274
hardReset,
246275
parseUrlParams,
247276
};
248-
}
277+
}

0 commit comments

Comments
 (0)