Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Analsysis: Should we allow (in a standardised way) checkbox support for individual data model fields for each alternative #789

Open
allinox opened this issue May 19, 2021 · 3 comments
Assignees
Labels

Comments

@allinox
Copy link
Contributor

allinox commented May 19, 2021

Analysis description

See the description below. In grooming, there was a debate if we think this should be something we facilitate being possible.

Scope of analysis

  • Define pros and cons for doing this change
  • If cons outweigh pros; define if we have an alternative solution for same need

Analysis

TBA

Conclusion

TBA

Original feature request

How it is now

As it is, the checkbox component stores all selected alternatives in one single field of the data model.
However, some data models expect the choices to be stored in separate fields for each of the alternatives and this isn't possible with the current component.

I know that there is a work-around where you can make a new field in the data model for storing all choices made in the question before separating this into the different fields already existing in the data model through coding in CalculationHandler, but doing this for every such question adds a lot of extra hours to the work-load (especially considering that checkboxes are pretty commonly used in forms). For example, I'm currently working on a form with around 24 different checkbox questions, which means a lot of extra work and a lot of extra calculations that will have to run when using the app.

How I'd like it to be

I'd like the option to enter more than one data model field for storing, one for each alternative.

A suggestion

Developers are already given the choice of entering the alternatives manually or through a code list.
Maybe a similar choice could be made between storage in one or multiple fields?
If the default is to store in one, maybe a change like this would break less of the already existing apps?
image

Additional context

There are likely a lot of forms in A2 that are currently using data models that expect the results of checkboxes to be stored in the fields of the individual alternatives, and thus their data ingestion system (mottakersystem) is expecting this as well.
I imagine the extra cost to either fix their model and system for A3 compliance or configure the A3-apps for the current data models would be a pretty big issue for potential costumers.

@allinox allinox added the kind/feature-request New feature or request label May 19, 2021
@lvbachmann lvbachmann changed the title Checkbox support for individual data model fields for each alternative Analsysis: Should we allow (in a standardised way) checkbox support for individual data model fields for each alternative Sep 3, 2021
@lvbachmann lvbachmann assigned altinnadmin and unassigned lvbachmann Dec 11, 2021
@ivarne
Copy link
Member

ivarne commented Dec 19, 2021

This should be looked at together with #114, because a natural way to implement different value strategies for checkboxes would be to use different datamodelbindings (as alternaltives to simpleBinding comma separated values)

@ivarne
Copy link
Member

ivarne commented Jan 11, 2022

After my attempts at cleaning up the checkbox component in Altinn/altinn-studio#7718 and Altinn/altinn-studio#7775, I finally think I understand what the component does, well enough to do changes. My suggestion to support individual bindings would be the following change, and it seems to work, but unfortunately I'll need to spend a few more days trying to understand how the checkboxes component is displayed in other contexts (summary, pdf, groups...), so I can make the multiple binding approach work there as well as making it supported in Altinn studio.

diff --git a/src/Altinn.Apps/AppFrontend/react/altinn-app-frontend/src/components/base/CheckboxesContainerComponent.tsx b/src/Altinn.Apps/AppFrontend/react/altinn-app-frontend/src/components/base/CheckboxesContainerComponent.tsx
index 00005a735..4ad2d7305 100644
--- a/src/Altinn.Apps/AppFrontend/react/altinn-app-frontend/src/components/base/CheckboxesContainerComponent.tsx
+++ b/src/Altinn.Apps/AppFrontend/react/altinn-app-frontend/src/components/base/CheckboxesContainerComponent.tsx
@@ -15,6 +15,8 @@ export interface ICheckboxContainerProps extends IComponentProps {
   options: IOption[];
   optionsId: string;
   preselectedOptionIndex?: number;
+  checkedValue?: string;
+  uncheckedValue?: string;
 }
 
 export interface IStyledCheckboxProps extends CheckboxProps {
@@ -76,11 +78,14 @@ export const CheckboxContainerComponent = (props: ICheckboxContainerProps) => {
   const apiOptions: IOption[] = useAppSelector(state => state.optionState.options[props.optionsId]);
   const options = apiOptions || props.options || emptyList;
   const checkBoxesIsRow: boolean = options.length <= 2;
+  const checkedValue = props.checkedValue ?? "true";
+  const uncheckedValue = props.uncheckedValue ?? "false"
 
   const selected = React.useMemo(() => {
-    return props.formData.simpleBinding.split(',').map(v => options.find(o => o.value == v)).filter(o => !!o) ?? emptyList;
-    // eslint-disable-next-line react-hooks/exhaustive-deps
-  }, [props.formData, options])
+    if (props.formData?.simpleBinding)
+      return props.formData.simpleBinding.split(',').map(v => options.find(o => o.value == v)).filter(o => !!o) ?? emptyList;
+    return Object.keys(props.formData).map(v => options.find(o => o.value == v)).filter(o => props.formData[o?.value] == checkedValue) ?? emptyList;
+  }, [props.formData, options, checkedValue])
 
   // Implement preselected functionality
   React.useEffect(() => {
@@ -103,8 +108,14 @@ export const CheckboxContainerComponent = (props: ICheckboxContainerProps) => {
     const newSelected = previouslySelected ?
       selected.filter(o => o.value !== event.target.name) :
       [...selected, options.find(o => o.value === event.target.name)];
-    props.handleDataChange(newSelected.map(o => o.value).join());
+    if(props.dataModelBindings["simpleBinding"]){
+      props.handleDataChange(newSelected.map(o => o.value).join(), "simpleBinding");
+    }
+
+    // Update box binding (if bindigns are set for each option)
+    if(props.dataModelBindings[event.target.name]){
+      props.handleDataChange(previouslySelected ? uncheckedValue : checkedValue, event.target.name)
+    }
   };
 
   const isOptionSelected = (option: IOption) => {

@olemartinorg
Copy link
Contributor

I suspect this is a (fancier) duplicate of #273. Also, #681 is very relevant here. Moving to app-frontend-react.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
Status: No status
Status: No status
Development

No branches or pull requests

6 participants