From 6fe20d3746b08f87530d91931d81a50da3d50248 Mon Sep 17 00:00:00 2001 From: Denis Lugowski Date: Sat, 27 Dec 2025 08:29:49 +0100 Subject: [PATCH] feat: Clear form element values when hidden --- .../components/FormStepperWithNavigation.vue | 21 ++++++- .../useFormElementValueClearing.ts | 59 +++++++++++++++++++ .../composables/useFormElementVisibility.ts | 4 +- .../application-forms/[id]/[sectionIndex].vue | 4 +- legalconsenthub/app/pages/create.vue | 4 +- 5 files changed, 84 insertions(+), 8 deletions(-) create mode 100644 legalconsenthub/app/composables/useFormElementValueClearing.ts diff --git a/legalconsenthub/app/components/FormStepperWithNavigation.vue b/legalconsenthub/app/components/FormStepperWithNavigation.vue index 4c1a82c..62f6428 100644 --- a/legalconsenthub/app/components/FormStepperWithNavigation.vue +++ b/legalconsenthub/app/components/FormStepperWithNavigation.vue @@ -99,10 +99,13 @@ const { stepper, activeStepperItemIndex, stepperItems, currentFormElementSection computed(() => props.formElementSections) ) -const { evaluateVisibility } = useFormElementVisibility() +const { evaluateFormElementVisibility } = useFormElementVisibility() +const { clearHiddenFormElementValues } = useFormElementValueClearing() const { processSpawnTriggers } = useSectionSpawning() const { cloneElement } = useClonableElements() +const previousVisibilityMap = ref>(new Map()) + const allFormElements = computed(() => { return props.formElementSections.flatMap( (section) => section.formElementSubSections?.flatMap((subsection) => subsection.formElements) ?? [] @@ -110,7 +113,7 @@ const allFormElements = computed(() => { }) const visibilityMap = computed(() => { - return evaluateVisibility(allFormElements.value) + return evaluateFormElementVisibility(allFormElements.value) }) const visibleSubsections = computed(() => { @@ -137,6 +140,7 @@ onMounted(() => { if (props.initialSectionIndex !== undefined) { activeStepperItemIndex.value = props.initialSectionIndex } + previousVisibilityMap.value = visibilityMap.value }) async function handleAddInputForm(position: number, subsectionKey: string) { @@ -191,9 +195,22 @@ function handleCloneElement(element: FormElementDto, position: number, subsectio function handleFormElementUpdate(updatedFormElements: FormElementDto[], subsectionKey: string) { let updatedSections = updateSubsectionElements(props.formElementSections, subsectionKey, updatedFormElements) updatedSections = processSpawnTriggers(updatedSections, updatedFormElements) + updatedSections = clearNewlyHiddenFormElements(updatedSections) emit('update:formElementSections', updatedSections) } +function clearNewlyHiddenFormElements(sections: FormElementSectionDto[]): FormElementSectionDto[] { + const allElements = sections.flatMap( + (section) => section.formElementSubSections?.flatMap((subsection) => subsection.formElements) ?? [] + ) + const newVisibilityMap = evaluateFormElementVisibility(allElements) + + const clearedSections = clearHiddenFormElementValues(sections, previousVisibilityMap.value, newVisibilityMap) + previousVisibilityMap.value = newVisibilityMap + + return clearedSections +} + function getSubsectionKey( section: FormElementSectionDto | undefined, sectionIndex: number, diff --git a/legalconsenthub/app/composables/useFormElementValueClearing.ts b/legalconsenthub/app/composables/useFormElementValueClearing.ts new file mode 100644 index 0000000..39be39a --- /dev/null +++ b/legalconsenthub/app/composables/useFormElementValueClearing.ts @@ -0,0 +1,59 @@ +import type { FormElementDto, FormElementSectionDto } from '~~/.api-client' + +export function useFormElementValueClearing() { + function clearHiddenFormElementValues( + sections: FormElementSectionDto[], + previousVisibilityMap: Map, + currentVisibilityMap: Map + ): FormElementSectionDto[] { + const elementsToClean = findNewlyHiddenFormElements(previousVisibilityMap, currentVisibilityMap) + if (elementsToClean.size === 0) { + return sections + } + + return sections.map((section) => ({ + ...section, + formElementSubSections: section.formElementSubSections.map((subsection) => ({ + ...subsection, + formElements: subsection.formElements.map((element) => { + const key = element.id || element.reference + if (key && elementsToClean.has(key)) { + return clearFormElementValue(element) + } + return element + }) + })) + })) + } + + function findNewlyHiddenFormElements( + previousMap: Map, + currentMap: Map + ): Set { + const newlyHidden = new Set() + currentMap.forEach((isVisible, key) => { + const wasVisible = previousMap.get(key) !== false + if (wasVisible && !isVisible) { + newlyHidden.add(key) + } + }) + return newlyHidden + } + + function clearFormElementValue(element: FormElementDto): FormElementDto { + if (['RADIOBUTTON', 'SELECT', 'CHECKBOX'].includes(element.type)) { + return { + ...element, + options: element.options.map((opt) => ({ ...opt, value: 'false' })) + } + } + return { + ...element, + options: element.options.map((opt, i) => (i === 0 ? { ...opt, value: '' } : opt)) + } + } + + return { + clearHiddenFormElementValues + } +} diff --git a/legalconsenthub/app/composables/useFormElementVisibility.ts b/legalconsenthub/app/composables/useFormElementVisibility.ts index 97afca8..131c348 100644 --- a/legalconsenthub/app/composables/useFormElementVisibility.ts +++ b/legalconsenthub/app/composables/useFormElementVisibility.ts @@ -2,7 +2,7 @@ import type { FormElementDto, VisibilityConditionOperator } from '~~/.api-client import { VisibilityConditionOperator as VCOperator, VisibilityConditionType as VCType } from '~~/.api-client' export function useFormElementVisibility() { - function evaluateVisibility(allFormElements: FormElementDto[]): Map { + function evaluateFormElementVisibility(allFormElements: FormElementDto[]): Map { const formElementsByRef = buildFormElementsMap(allFormElements) const visibilityMap = new Map() @@ -81,6 +81,6 @@ export function useFormElementVisibility() { } return { - evaluateVisibility + evaluateFormElementVisibility } } diff --git a/legalconsenthub/app/pages/application-forms/[id]/[sectionIndex].vue b/legalconsenthub/app/pages/application-forms/[id]/[sectionIndex].vue index c51e034..b1d37bd 100644 --- a/legalconsenthub/app/pages/application-forms/[id]/[sectionIndex].vue +++ b/legalconsenthub/app/pages/application-forms/[id]/[sectionIndex].vue @@ -82,7 +82,7 @@ if (applicationFormId) { const { updateApplicationForm: updateForm, submitApplicationForm } = useApplicationForm() const { validateFormElements, getHighestComplianceStatus } = useApplicationFormValidator() -const { evaluateVisibility } = useFormElementVisibility() +const { evaluateFormElementVisibility } = useFormElementVisibility() const { canWriteApplicationForms } = usePermissions() const userStore = useUserStore() const { user } = storeToRefs(userStore) @@ -109,7 +109,7 @@ const allFormElements = computed(() => { }) const visibilityMap = computed(() => { - return evaluateVisibility(allFormElements.value) + return evaluateFormElementVisibility(allFormElements.value) }) watch( diff --git a/legalconsenthub/app/pages/create.vue b/legalconsenthub/app/pages/create.vue index f6eeed2..3bf6204 100644 --- a/legalconsenthub/app/pages/create.vue +++ b/legalconsenthub/app/pages/create.vue @@ -54,7 +54,7 @@ import { useUserStore } from '~~/stores/useUserStore' const { getAllApplicationFormTemplates } = useApplicationFormTemplate() const { createApplicationForm, submitApplicationForm } = useApplicationForm() const { validateFormElements, getHighestComplianceStatus } = useApplicationFormValidator() -const { evaluateVisibility } = useFormElementVisibility() +const { evaluateFormElementVisibility } = useFormElementVisibility() const { canWriteApplicationForms } = usePermissions() const userStore = useUserStore() const { selectedOrganization } = storeToRefs(userStore) @@ -91,7 +91,7 @@ const allFormElements = computed(() => { }) const visibilityMap = computed(() => { - return evaluateVisibility(allFormElements.value) + return evaluateFormElementVisibility(allFormElements.value) }) watch(