moving towards real data

This commit is contained in:
Casey 2025-11-06 13:00:19 -06:00
parent ac3c05cb78
commit 40c4a5a37f
8 changed files with 303 additions and 84 deletions

View file

@ -1,6 +1,6 @@
<template lang="html">
<!-- Filter Controls Panel -->
<div v-if="lazy && hasFilters" class="filter-controls-panel mb-3 p-3 bg-light rounded">
<div v-if="hasFilters" class="filter-controls-panel mb-3 p-3 bg-light rounded">
<div class="row g-3 align-items-end">
<div v-for="col in filterableColumns" :key="col.fieldName" class="col-md-4 col-lg-3">
<label :for="`filter-${col.fieldName}`" class="form-label small fw-semibold">
@ -41,7 +41,7 @@
</div>
<!-- Page Jump Controls -->
<div v-if="lazy && totalPages > 1" class="page-controls-panel mb-3 p-2 bg-light rounded">
<div v-if="totalPages > 1" class="page-controls-panel mb-3 p-2 bg-light rounded">
<div class="row g-3 align-items-center">
<div class="col-auto">
<small class="text-muted">Quick navigation:</small>
@ -69,12 +69,13 @@
</div>
<DataTable
ref="dataTableRef"
:value="data"
:rowsPerPageOptions="[5, 10, 20, 50]"
:paginator="true"
:rows="currentRows"
:lazy="lazy"
:totalRecords="lazy ? totalRecords : data.length"
:totalRecords="lazy ? totalRecords : getFilteredDataLength"
@page="handlePage"
@sort="handleSort"
@filter="handleFilter"
@ -201,6 +202,11 @@ const props = defineProps({
type: Number,
default: 0,
},
// Total filtered records for non-lazy tables (when server-side filtering is used)
totalFilteredRecords: {
type: Number,
default: null,
},
// Custom pagination event handler
onLazyLoad: {
type: Function,
@ -208,7 +214,14 @@ const props = defineProps({
},
});
const emit = defineEmits(["rowClick", "lazy-load", "page-change", "sort-change", "filter-change"]);
const emit = defineEmits([
"rowClick",
"lazy-load",
"page-change",
"sort-change",
"filter-change",
"data-refresh",
]);
// Computed loading state that considers both prop and global store
const loading = computed(() => {
@ -292,6 +305,8 @@ watch(
const selectedRows = ref();
const pendingFilters = ref({});
const selectedPageJump = ref("");
const dataTableRef = ref();
const currentPageState = ref({ page: 0, first: 0 }); // Track current page for non-lazy tables
// Computed properties for filtering
const filterableColumns = computed(() => {
@ -319,8 +334,12 @@ const hasFilterChanges = computed(() => {
});
const totalPages = computed(() => {
if (!props.lazy) return 0;
return paginationStore.getTotalPages(props.tableName);
if (props.lazy) {
return paginationStore.getTotalPages(props.tableName);
}
// For non-lazy tables, calculate based on current filtered data
const filteredDataLength = getFilteredDataLength.value;
return Math.ceil(filteredDataLength / currentRows.value) || 1;
});
// Initialize pending filters from store
@ -331,6 +350,17 @@ onMounted(() => {
});
});
// Computed property to get filtered data length for non-lazy tables
const getFilteredDataLength = computed(() => {
if (props.lazy) {
return props.totalRecords;
}
// For non-lazy tables, use totalFilteredRecords if provided (server-side filtering),
// otherwise fall back to data length (client-side filtering)
return props.totalFilteredRecords !== null ? props.totalFilteredRecords : props.data.length;
});
// Filter management methods
const applyFilters = () => {
// Update store with pending filter values
@ -344,10 +374,16 @@ const applyFilters = () => {
);
});
// For lazy tables, reset to first page and trigger reload
// Reset to first page when filters change (for both lazy and non-lazy)
currentPageState.value = { page: 0, first: 0 };
// For both lazy and non-lazy tables, trigger reload with new filters
if (props.lazy) {
paginationStore.resetToFirstPage(props.tableName);
triggerLazyLoad();
} else {
// For non-lazy tables, also trigger a reload to get fresh data from server
triggerDataRefresh();
}
};
@ -360,10 +396,16 @@ const clearFilters = () => {
// Clear store filters
filtersStore.clearTableFilters(props.tableName);
// For lazy tables, reset to first page and trigger reload
// Reset to first page when filters are cleared (for both lazy and non-lazy)
currentPageState.value = { page: 0, first: 0 };
// For both lazy and non-lazy tables, trigger reload with cleared filters
if (props.lazy) {
paginationStore.resetToFirstPage(props.tableName);
triggerLazyLoad();
} else {
// For non-lazy tables, also trigger a reload to get fresh data from server
triggerDataRefresh();
}
};
@ -383,21 +425,53 @@ const getActiveFiltersText = () => {
// Page navigation methods
const jumpToPage = () => {
if (selectedPageJump.value && props.lazy) {
if (selectedPageJump.value) {
const pageNumber = parseInt(selectedPageJump.value) - 1; // Convert to 0-based
paginationStore.setPage(props.tableName, pageNumber);
triggerLazyLoad();
if (props.lazy) {
paginationStore.setPage(props.tableName, pageNumber);
triggerLazyLoad();
} else {
// For non-lazy tables, update our internal state
// The DataTable will handle the actual pagination
currentPageState.value = {
page: pageNumber,
first: pageNumber * currentRows.value,
};
}
}
selectedPageJump.value = ""; // Reset selection
};
const getPageInfo = () => {
return paginationStore.getPageInfo(props.tableName);
if (props.lazy) {
return paginationStore.getPageInfo(props.tableName);
}
// For non-lazy tables, calculate based on current page state and filtered data
const filteredTotal = getFilteredDataLength.value;
const rows = currentRows.value;
const currentFirst = currentPageState.value.first;
const start = filteredTotal > 0 ? currentFirst + 1 : 0;
const end = Math.min(filteredTotal, currentFirst + rows);
return {
start,
end,
total: filteredTotal,
};
};
// Handle pagination events
const handlePage = (event) => {
console.log("Page event:", event);
// Update current page state for both lazy and non-lazy tables
currentPageState.value = {
page: event.page,
first: event.first,
};
if (props.lazy) {
paginationStore.updateTablePagination(props.tableName, {
page: event.page,
@ -424,8 +498,11 @@ const handleSort = (event) => {
// Handle filter events
const handleFilter = (event) => {
console.log("Filter event:", event);
// Reset to first page when filters change (for both lazy and non-lazy)
currentPageState.value = { page: 0, first: 0 };
if (props.lazy) {
// Reset to first page when filters change
paginationStore.resetToFirstPage(props.tableName);
triggerLazyLoad();
}
@ -453,6 +530,37 @@ const triggerLazyLoad = () => {
}
};
// Trigger data refresh for non-lazy tables when filters change
const triggerDataRefresh = () => {
const filters = filtersStore.getTableFilters(props.tableName);
const refreshEvent = {
filters: filters,
page: currentPageState.value.page,
first: currentPageState.value.first,
rows: currentRows.value,
};
console.log("Triggering data refresh with:", refreshEvent);
emit("data-refresh", refreshEvent);
};
const handleFilterInput = (fieldName, value, filterCallback) => {
// Update the filter store
filtersStore.updateTableFilter(props.tableName, fieldName, value, FilterMatchMode.CONTAINS);
// Call the PrimeVue callback to update the filter
if (filterCallback) {
filterCallback();
}
// For non-lazy tables, also trigger a data refresh when individual filters change
if (!props.lazy) {
// Reset to first page when filters change
currentPageState.value = { page: 0, first: 0 };
triggerDataRefresh();
}
};
const getBadgeColor = (status) => {
console.log("DEBUG: - getBadgeColor status", status);
switch (status?.toLowerCase()) {
@ -498,6 +606,8 @@ defineExpose({
refresh: () => {
if (props.lazy) {
triggerLazyLoad();
} else {
triggerDataRefresh();
}
},

View file

@ -1,5 +1,5 @@
<template>
<form @submit.prevent="handleSubmit" class="dynamic-form">
<form class="dynamic-form">
<div class="form-container">
<div class="form-row">
<div
@ -372,11 +372,12 @@
<div v-if="showSubmitButton || showCancelButton" class="form-buttons">
<Button
v-if="showSubmitButton"
type="submit"
type="button"
:label="submitButtonText"
:loading="isLoading"
:disabled="isFormDisabled"
severity="primary"
@click="handleSubmit"
/>
<Button
v-if="showCancelButton"
@ -839,9 +840,15 @@ const validateForm = () => {
// Handle form submission
const handleSubmit = async () => {
// Prevent double submission
if (isSubmitting.value) {
console.warn("Form: submission already in progress, ignoring duplicate submission");
return;
}
// Always validate on submit if enabled
if (props.validateOnSubmit && !validateForm()) {
console.warn("Form validation failed on submit");
console.warn("Form: validation failed on submit");
return;
}
@ -849,17 +856,23 @@ const handleSubmit = async () => {
try {
const formData = getCurrentFormData();
console.log("Form: emitting submit event with data:", formData);
// Only emit the submit event - let parent handle the actual submission
// This prevents the dual submission pathway issue
emit("submit", formData);
// Call onSubmit prop if provided (for backward compatibility)
if (props.onSubmit && typeof props.onSubmit === "function") {
await props.onSubmit(formData);
}
emit("submit", formData);
} catch (error) {
console.error("Form submission error:", error);
} finally {
console.error("Form: submission error:", error);
// Reset isSubmitting on error so user can retry
isSubmitting.value = false;
}
// Note: Don't reset isSubmitting.value here in finally - let parent control this
// The parent should call the exposed stopLoading() method when done
};
// Handle cancel action