9.4 KiB
Validation Display Issue Implementation
Issue Being Addressed
Validation Display Issue: Validation isn't happening beyond checking if a cell is required or not. All validation rules defined in import.tsx need to be respected.
- Required fields correctly show a red border when empty (✅ ALREADY WORKING)
- Non-empty fields with validation errors (regex, unique, etc.) should show a red border AND an alert circle icon with tooltip explaining the error (❌ NOT WORKING)
Implementation Attempts
!!!!NOTE All previous attempts have been reverted and are no longer part of the code, please take this into account when trying a new solution. !!!!
Attempt 1: Fix Validation Display Logic
Approach: Modified processErrors function to separate required errors from validation errors and show alert icons only for non-empty fields with validation errors.
Changes Made:
function processErrors(value: any, errors: ErrorObject[]) {
// ...existing code...
// Separate required errors from other validation errors
const requiredErrors = errors.filter(error =>
error.message?.toLowerCase().includes('required')
);
const validationErrors = errors.filter(error =>
!error.message?.toLowerCase().includes('required')
);
const isRequiredButEmpty = valueIsEmpty && requiredErrors.length > 0;
const hasValidationErrors = validationErrors.length > 0;
const shouldShowErrorIcon = hasValidationErrors && !valueIsEmpty;
// ...more code...
}
Result: Non-empty fields with validation errors still aren't displaying the alert icon with tooltip.
Attempt 2: Comprehensive Fix for Validation Display
Approach: Completely rewrote processErrors function with consistent empty value detection, clear error separation, and improved error message extraction.
Changes Made:
function processErrors(value: any, errors: ErrorObject[]) {
if (!errors || errors.length === 0) {
return { filteredErrors: [], hasError: false, isRequiredButEmpty: false,
shouldShowErrorIcon: false, errorMessages: '' };
}
const valueIsEmpty = isEmpty(value);
const requiredErrors = errors.filter(error =>
error.message?.toLowerCase().includes('required')
);
const validationErrors = errors.filter(error =>
!error.message?.toLowerCase().includes('required')
);
let filteredErrors = valueIsEmpty ? requiredErrors : validationErrors;
const isRequiredButEmpty = valueIsEmpty && requiredErrors.length > 0;
const hasValidationErrors = validationErrors.length > 0;
const hasError = isRequiredButEmpty || hasValidationErrors;
const shouldShowErrorIcon = hasValidationErrors && !valueIsEmpty;
let errorMessages = '';
if (shouldShowErrorIcon) {
errorMessages = validationErrors.map(getErrorMessage).join('\n');
}
return { filteredErrors, hasError, isRequiredButEmpty, shouldShowErrorIcon, errorMessages };
}
Result: Non-empty fields with validation errors still aren't displaying the alert icon with tooltip.
Attempt 3: Simplified Error Processing Logic
Approach: Refactored processErrors to use shared isEmpty function, simplified error icon logic, and made error message extraction more direct.
Changes Made:
function processErrors(value: any, errors: ErrorObject[]) {
if (!errors || errors.length === 0) {
return { filteredErrors: [], hasError: false, isRequiredButEmpty: false,
shouldShowErrorIcon: false, errorMessages: '' };
}
const valueIsEmpty = isEmpty(value);
const requiredErrors = errors.filter(error =>
error.message?.toLowerCase().includes('required')
);
const validationErrors = errors.filter(error =>
!error.message?.toLowerCase().includes('required')
);
let filteredErrors = valueIsEmpty ? requiredErrors : validationErrors;
const isRequiredButEmpty = valueIsEmpty && requiredErrors.length > 0;
const hasValidationErrors = !valueIsEmpty && validationErrors.length > 0;
const hasError = isRequiredButEmpty || hasValidationErrors;
const shouldShowErrorIcon = hasValidationErrors;
let errorMessages = '';
if (shouldShowErrorIcon) {
errorMessages = validationErrors.map(getErrorMessage).join('\n');
}
return { filteredErrors, hasError, isRequiredButEmpty, shouldShowErrorIcon, errorMessages };
}
Result: Non-empty fields with validation errors still aren't displaying the alert icon with tooltip.
Attempt 4: Consistent Error Processing Across Components
Approach: Updated both processErrors function and ValidationCell component to ensure consistent error handling between components.
Changes Made:
// In processErrors function
function processErrors(value: any, errors: ErrorObject[]) {
// Similar to Attempt 3 with consistent error handling
}
// In ValidationCell component
const ValidationCell = ({ field, value, onChange, errors, /* other props */ }) => {
// ...existing code...
// Use the processErrors function to handle validation errors
const { hasError, isRequiredButEmpty, shouldShowErrorIcon, errorMessages } =
React.useMemo(() => processErrors(value, errors), [value, errors]);
// ...rest of the component...
}
Result: Non-empty fields with validation errors still aren't displaying the alert icon with tooltip.
Attempt 5: Unified Error Processing with ItemNumberCell
Approach: Replaced custom error processing in ValidationCell with the same processErrors utility used by ItemNumberCell.
Changes Made:
const ValidationCell = ({ field, value, onChange, errors, /* other props */ }) => {
// State and context setup...
// For item_number fields, use the specialized component
if (fieldKey === 'item_number') {
return <ItemNumberCell {...props} />;
}
// Use the same processErrors utility function that ItemNumberCell uses
const { hasError, isRequiredButEmpty, shouldShowErrorIcon, errorMessages } =
React.useMemo(() => processErrors(value, errors), [value, errors]);
// Rest of component...
}
Result: Non-empty fields with validation errors still aren't displaying the alert icon with tooltip.
Attempt 6: Standardize Error Processing Across Cell Types
Approach: Standardized error handling across all cell types using the shared processErrors utility function.
Changes Made: Similar to Attempt 5, with focus on standardizing the approach for determining when to show validation error icons.
Result: Non-empty fields with validation errors still aren't displaying the alert icon with tooltip.
Attempt 7: Replace Custom Error Processing with Shared Utility
Approach: Ensured consistent error handling between ItemNumberCell and regular ValidationCell components.
Changes Made: Similar to Attempts 5 and 6, with focus on using the shared utility function consistently.
Result: Non-empty fields with validation errors still aren't displaying the alert icon with tooltip.
Attempt 8: Improved Error Normalization and Deep Comparison
Approach: Modified MemoizedCell in ValidationTable.tsx to use deep comparison for error objects and improved error normalization.
Changes Made:
// Create a memoized cell component
const MemoizedCell = React.memo(({ field, value, onChange, errors, /* other props */ }) => {
return <ValidationCell {...props} />;
}, (prev, next) => {
// Basic prop comparison
if (prev.value !== next.value) return false;
if (prev.isValidating !== next.isValidating) return false;
if (prev.itemNumber !== next.itemNumber) return false;
// Deep compare errors - critical for validation display
if (!prev.errors && next.errors) return false;
if (prev.errors && !next.errors) return false;
if (prev.errors && next.errors) {
if (prev.errors.length !== next.errors.length) return false;
// Compare each error object
for (let i = 0; i < prev.errors.length; i++) {
if (prev.errors[i].message !== next.errors[i].message) return false;
if (prev.errors[i].level !== next.errors[i].level) return false;
if (prev.errors[i].source !== next.errors[i].source) return false;
}
}
// Compare options...
return true;
});
// In the field columns definition:
cell: ({ row }) => {
const rowErrors = validationErrors.get(row.index);
const cellErrors = rowErrors?.[fieldKey] || [];
// Ensure cellErrors is always an array
const normalizedErrors = Array.isArray(cellErrors) ? cellErrors : [cellErrors];
return <MemoizedCell {...props} errors={normalizedErrors} />;
}
Result: Non-empty fields with validation errors still aren't displaying the alert icon with tooltip.
Root Causes (Revised Hypothesis)
After multiple attempts, the issue appears more complex than initially thought. Possible root causes:
- Error Object Structure: Error objects might not have the expected structure or properties
- Error Propagation: Errors might be getting filtered out before reaching cell components
- Validation Rules Configuration: Validation rules in import.tsx might be incorrectly configured
- Error State Management: Error state might not be properly updated or might be reset incorrectly
- Component Rendering Logic: Components might not re-render when validation state changes
- CSS/Styling Issues: Validation icons might be rendered but hidden due to styling issues
- Validation Timing: Validation might be happening at the wrong time or getting overridden