Skip to content

Commit

Permalink
Form improvements / fixes:
Browse files Browse the repository at this point in the history
- Don't validate hidden fields
- In form controls, also pass cleanValue
- Cleanup: validate() returning "true" means "hasErrors"
- ArrayList:
  - execute the dropEmptyItems action after validation,
    independently of value cleanup.
  - If there are only empty values, consider the whole value empty,
    and don't validate
- Field group validation:
  - ignore visibility (it is handle internally in each field's validation)
  - sort out boolean semantics and logics
  • Loading branch information
csillag committed Oct 12, 2024
1 parent 6cbdf15 commit b4b72c6
Show file tree
Hide file tree
Showing 3 changed files with 23 additions and 17 deletions.
8 changes: 7 additions & 1 deletion frontend/src/components/InputFields/useInputField.ts
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,7 @@ export type InputFieldControls<DataType> = Pick<
whyDisabled?: MarkdownCode
containerClassName?: string
value: DataType
cleanValue: DataType
setValue: (value: DataType) => void
reset: () => void
allMessages: AllMessages
Expand Down Expand Up @@ -312,6 +313,10 @@ export function useInputField<DataType>(
}

const validate = async (params: ValidationParams): Promise<boolean> => {
if (!visible) {
// We don't care about hidden fields
return false
}
const { forceChange = false, reason, isStillFresh } = params
const wasOK = isValidated && !hasProblems

Expand Down Expand Up @@ -371,7 +376,7 @@ export function useInputField<DataType>(
setLastValidatedData(cleanValue)

// Do we have any actual errors?
return !currentMessages.some(message => message.type === 'error')
return currentMessages.some(message => message.type === 'error')
} else {
return false
}
Expand Down Expand Up @@ -422,6 +427,7 @@ export function useInputField<DataType>(
compact,
placeholder,
value,
cleanValue,
setValue,
reset,
allMessages: allMessages,
Expand Down
23 changes: 11 additions & 12 deletions frontend/src/components/InputFields/useTextArrayField.ts
Original file line number Diff line number Diff line change
Expand Up @@ -234,16 +234,7 @@ export function useTextArrayField(props: TextArrayProps): TextArrayControls {
{
...props,
initialValue,
cleanUp: values => {
let cleanValues = values.map(s => s.trim())
if (dropEmptyItems) {
const filteredValues = cleanValues.filter(s => !!s)
if (!minItemCount || filteredValues.length >= minItemCount) {
cleanValues = filteredValues
}
}
return cleanValues
},
cleanUp: values => values.map(s => s.trim()),
validators: undefined,
validatorsGenerator: values => [
// Do we have enough elements?
Expand All @@ -257,7 +248,7 @@ export function useTextArrayField(props: TextArrayProps): TextArrayControls {
: undefined,

// No empty elements, please
allowEmptyItems && dropEmptyItems
allowEmptyItems || dropEmptyItems
? undefined
: (values, _control, reason) =>
reason === 'change'
Expand Down Expand Up @@ -338,7 +329,7 @@ export function useTextArrayField(props: TextArrayProps): TextArrayControls {
],
},
{
isEmpty: value => !value.length,
isEmpty: value => !value.some(v => !!v),
isEqual: (a, b) => a.join('-') === b.join('-'),
},
)
Expand Down Expand Up @@ -382,5 +373,13 @@ export function useTextArrayField(props: TextArrayProps): TextArrayControls {
}
}

newControls.validate = async params => {
const hasError = await controls.validate(params)
if (!hasError && dropEmptyItems) {
controls.setValue(controls.cleanValue.filter(s => !!s))
}
return hasError
}

return newControls
}
9 changes: 5 additions & 4 deletions frontend/src/components/InputFields/validation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,12 @@ export const validateFields = async (
*/
isStillFresh: () => boolean,
): Promise<boolean> => {
const visibleFields = fields.flatMap(config => getAsArray(config)).filter(field => field.visible)
// Get a flattened list of fields
const allFields = fields.flatMap(config => getAsArray(config))
let hasError = false
for (const field of visibleFields) {
const isFieldOK = await field.validate({ reason, isStillFresh })
hasError = hasError || !isFieldOK
for (const field of allFields) {
const isFieldProblematic = await field.validate({ reason, isStillFresh })
hasError = hasError || isFieldProblematic
}
return hasError
}
Expand Down

0 comments on commit b4b72c6

Please sign in to comment.