Skip to content

Commit aad10fd

Browse files
authored
Merge pull request #25 from workfloworchestrator/1711-Pydanticforms-basic--Multiselect-checkboxes
[1711] enable multicheckbox
2 parents fac4029 + ea5591f commit aad10fd

File tree

4 files changed

+85
-1
lines changed

4 files changed

+85
-1
lines changed

backend/main.py

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,14 @@
2121
from pydantic_forms.exceptions import FormException
2222
from pydantic_forms.core import FormPage as PydanticFormsFormPage
2323
from pydantic_forms.types import JSON
24-
from pydantic_forms.validators import LongText, Label, Divider, Hidden, Choice
24+
from pydantic_forms.validators import (
25+
LongText,
26+
Label,
27+
Divider,
28+
Hidden,
29+
Choice,
30+
choice_list,
31+
)
2532

2633
# Choice,
2734
# CustomerId,
@@ -88,6 +95,13 @@ class RadioChoices(Choice):
8895
_3 = ("3", "Option 3")
8996

9097

98+
class MultiCheckBoxChoices(Choice):
99+
_1 = ("1", "Option 1")
100+
_2 = ("2", "Option 2")
101+
_3 = ("3", "Option 3")
102+
_4 = ("4", "Option 4")
103+
104+
91105
@app.post("/form")
92106
async def form(form_data: list[dict] = []):
93107
def form_generator(state: State):
@@ -105,6 +119,7 @@ class TestForm(FormPage):
105119
# When there are <= 3 choices a radio group will be rendered
106120
radio: RadioChoices = "3"
107121
checkbox: bool = True
122+
multicheckbox: choice_list(MultiCheckBoxChoices, min_items=3)
108123

109124
form_data_1 = yield TestForm
110125

frontend/packages/pydantic-forms/src/components/defaultComponentMatchers.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import {
1010
HiddenField,
1111
IntegerField,
1212
LabelField,
13+
MultiCheckboxField,
1314
RadioField,
1415
TextAreaField,
1516
} from '@/components/fields';
@@ -125,6 +126,20 @@ const defaultComponentMatchers: PydanticComponentMatcher[] = [
125126
return field.type === PydanticFormFieldType.BOOLEAN;
126127
},
127128
},
129+
{
130+
id: 'multicheckbox',
131+
ElementMatch: {
132+
Element: MultiCheckboxField,
133+
isControlledElement: true,
134+
},
135+
matcher(field) {
136+
// Use this component when we have multiple boolean options (5 or more)
137+
return (
138+
field.type === PydanticFormFieldType.ARRAY &&
139+
field.options.length <= 5
140+
);
141+
},
142+
},
128143
];
129144

130145
// If nothing matches, it defaults to Text field in the mapToComponent function
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
/**
2+
* Pydantic Forms
3+
*
4+
* MultiCheckbox component for handling multiple boolean selections
5+
*/
6+
import React from 'react';
7+
8+
import {
9+
PydanticFormControlledElementProps,
10+
PydanticFormFieldOption,
11+
} from '@/types';
12+
13+
export const MultiCheckboxField = ({
14+
value,
15+
onChange,
16+
pydanticFormField,
17+
}: PydanticFormControlledElementProps) => {
18+
const { options, id } = pydanticFormField;
19+
20+
const handleCheckboxChange = (optionId: string, optionValue: string) => {
21+
const currentValue = value as string[];
22+
const newValue = currentValue.includes(optionValue)
23+
? currentValue.filter((item) => item !== optionValue)
24+
: [...currentValue, optionValue];
25+
26+
onChange(newValue);
27+
};
28+
29+
return (
30+
<div>
31+
{options.map((option: PydanticFormFieldOption) => {
32+
// Extract the unique ID for this option
33+
const optionId = `${id}-${option.value}`;
34+
35+
return (
36+
<label key={optionId}>
37+
<input
38+
type="checkbox"
39+
id={optionId}
40+
name={optionId}
41+
value={option.value}
42+
checked={(value as string[]).includes(option.value)}
43+
onChange={() =>
44+
handleCheckboxChange(optionId, option.value)
45+
}
46+
/>
47+
<span>{option.label || option.value}</span>
48+
</label>
49+
);
50+
})}
51+
</div>
52+
);
53+
};

frontend/packages/pydantic-forms/src/components/fields/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,4 @@ export * from './DividerField';
99
export * from './HiddenField';
1010
export * from './DropdownField';
1111
export * from './RadioField';
12+
export * from './MultiCheckboxField';

0 commit comments

Comments
 (0)