Skip to content

Commit aaa5602

Browse files
authored
Merge pull request #22 from workfloworchestrator/1694-option-fields
1694 option fields
2 parents 703085d + e4ea8e1 commit aaa5602

File tree

5 files changed

+115
-1
lines changed

5 files changed

+115
-1
lines changed

backend/main.py

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
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
24+
from pydantic_forms.validators import LongText, Label, Divider, Hidden, Choice
2525

2626
# Choice,
2727
# CustomerId,
@@ -75,6 +75,19 @@ def example_backend_validation(val: int) -> bool:
7575
]
7676

7777

78+
class DropdownChoices(Choice):
79+
_1 = ("1", "Option 1")
80+
_2 = ("2", "Option 2")
81+
_3 = ("3", "Option 3")
82+
_4 = ("4", "Option 4")
83+
84+
85+
class RadioChoices(Choice):
86+
_1 = ("1", "Option 1")
87+
_2 = ("2", "Option 2")
88+
_3 = ("3", "Option 3")
89+
90+
7891
@app.post("/form")
7992
async def form(form_data: list[dict] = []):
8093
def form_generator(state: State):
@@ -87,6 +100,10 @@ class TestForm(FormPage):
87100
divider: Divider
88101
label: Label = "Label"
89102
hidden: Hidden = "Hidden"
103+
# When there are > 3 choices a dropdown will be rendered
104+
dropdown: DropdownChoices = ("2")
105+
# When there are <= 3 choices a radio group will be rendered
106+
radio: RadioChoices = ("3")
90107

91108
form_data_1 = yield TestForm
92109

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

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,11 @@
55
*/
66
import {
77
DividerField,
8+
DropdownField,
89
HiddenField,
910
IntegerField,
1011
LabelField,
12+
RadioField,
1113
TextAreaField,
1214
} from '@/components/fields';
1315
import {
@@ -83,6 +85,35 @@ const defaultComponentMatchers: PydanticComponentMatcher[] = [
8385
);
8486
},
8587
},
88+
{
89+
id: 'radio',
90+
ElementMatch: {
91+
Element: RadioField,
92+
isControlledElement: true,
93+
},
94+
matcher(field) {
95+
// We are looking for a single value from a set list of options. With less than 4 options, use radio buttons.
96+
return (
97+
field.type === PydanticFormFieldType.STRING &&
98+
field.options.length > 0 &&
99+
field.options.length <= 3
100+
);
101+
},
102+
},
103+
{
104+
id: 'dropdown',
105+
ElementMatch: {
106+
Element: DropdownField,
107+
isControlledElement: true,
108+
},
109+
matcher(field) {
110+
// We are looking for a single value from a set list of options. With more than 3 options, use a dropdown.
111+
return (
112+
field.type === PydanticFormFieldType.STRING &&
113+
field.options.length >= 4
114+
);
115+
},
116+
},
86117
];
87118
// If nothing matches, it defaults to Text field in the mapToComponent function
88119
export default defaultComponentMatchers;
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/**
2+
* Pydantic Forms
3+
*
4+
* Text component
5+
*/
6+
import React from 'react';
7+
8+
import { PydanticFormControlledElementProps } from '@/types';
9+
10+
export const DropdownField = ({
11+
value,
12+
onChange,
13+
pydanticFormField,
14+
}: PydanticFormControlledElementProps) => {
15+
return (
16+
<select
17+
value={value}
18+
onChange={(e) => {
19+
onChange(e.target.value);
20+
}}
21+
disabled={!!pydanticFormField.attributes.disabled}
22+
>
23+
{pydanticFormField.options?.map((option) => (
24+
<option key={option.value} value={option.value}>
25+
{option.label}
26+
</option>
27+
))}
28+
</select>
29+
);
30+
};
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/**
2+
* Pydantic Forms
3+
*
4+
* Text component
5+
*/
6+
import React from 'react';
7+
8+
import { PydanticFormControlledElementProps } from '@/types';
9+
10+
export const RadioField = ({
11+
value,
12+
onChange,
13+
pydanticFormField,
14+
}: PydanticFormControlledElementProps) => {
15+
const { options, id } = pydanticFormField;
16+
17+
return (
18+
<div>
19+
{options.map((option, key) => (
20+
<div key={key}>
21+
<input
22+
type="radio"
23+
id={option.value}
24+
name={id}
25+
value={option.value}
26+
checked={value === option.value}
27+
onChange={(e) => onChange(e.target.value)}
28+
/>
29+
 <label htmlFor={option.value}>{option.label}</label>
30+
</div>
31+
))}
32+
</div>
33+
);
34+
};

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,5 @@ export * from './TextAreaField';
66
export * from './LabelField';
77
export * from './DividerField';
88
export * from './HiddenField';
9+
export * from './DropdownField';
10+
export * from './RadioField';

0 commit comments

Comments
 (0)