Skip to content

Commit e63d3fe

Browse files
committed
add multiselect check box
1 parent 5c0fbb8 commit e63d3fe

4 files changed

Lines changed: 149 additions & 2 deletions

File tree

src/core/components/DaisyTheme.tsx

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,11 @@ import {
1818
schemaRequiresTrueValue,
1919
descriptionId,
2020
ariaDescribedByIds,
21+
enumOptionsIsSelected,
22+
enumOptionsSelectValue,
23+
enumOptionsDeselectValue,
24+
enumOptionsValueForIndex,
25+
optionId,
2126
} from "@rjsf/utils"
2227
import ReactMarkdown from "react-markdown"
2328
import remarkGfm from "remark-gfm"
@@ -250,6 +255,63 @@ const MyCheckboxWidget = (props: WidgetProps) => {
250255
)
251256
}
252257

258+
const MyCheckboxesWidget = (props: WidgetProps) => {
259+
const {
260+
id,
261+
disabled,
262+
options,
263+
value,
264+
readonly,
265+
onChange,
266+
onBlur,
267+
onFocus,
268+
autofocus = false,
269+
} = props
270+
const { enumOptions, enumDisabled, emptyValue } = options
271+
const checkboxesValues = Array.isArray(value) ? value : [value]
272+
273+
return (
274+
<div className="checkboxes-group" id={id}>
275+
{Array.isArray(enumOptions) &&
276+
enumOptions.map((option, index) => {
277+
const checked = enumOptionsIsSelected(option.value, checkboxesValues)
278+
const itemDisabled =
279+
Array.isArray(enumDisabled) && enumDisabled.indexOf(option.value) !== -1
280+
const disabledCls = disabled || itemDisabled || readonly ? "disabled" : ""
281+
282+
return (
283+
<label key={index} className={`checkboxes-option ${disabledCls}`}>
284+
<input
285+
type="checkbox"
286+
id={optionId(id, index)}
287+
name={id}
288+
checked={checked}
289+
value={String(index)}
290+
disabled={disabled || itemDisabled || readonly}
291+
autoFocus={autofocus && index === 0}
292+
onChange={(event) => {
293+
if (event.target.checked) {
294+
onChange(enumOptionsSelectValue(index, checkboxesValues, enumOptions))
295+
} else {
296+
onChange(enumOptionsDeselectValue(index, checkboxesValues, enumOptions))
297+
}
298+
}}
299+
onBlur={({ target: { value: v } }) =>
300+
onBlur(id, enumOptionsValueForIndex(v, enumOptions, emptyValue))
301+
}
302+
onFocus={({ target: { value: v } }) =>
303+
onFocus(id, enumOptionsValueForIndex(v, enumOptions, emptyValue))
304+
}
305+
aria-describedby={ariaDescribedByIds(id)}
306+
/>
307+
<span>{option.label}</span>
308+
</label>
309+
)
310+
})}
311+
</div>
312+
)
313+
}
314+
253315
// create Registry information
254316
// templates
255317
const myTemplates: Partial<TemplatesType> = {
@@ -282,6 +344,7 @@ const myWidgets: RegistryWidgetsType = {
282344
TextWidget: MyTextWidget,
283345
EmailWidget: MyEmailWidget,
284346
CheckboxWidget: MyCheckboxWidget,
347+
CheckboxesWidget: MyCheckboxesWidget,
285348
}
286349

287350
// create the overall theme to use on the other page

src/core/styles/index.css

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -702,6 +702,23 @@ span.arrow.tooltip-arrow {
702702
margin-left: 30px;
703703
}
704704

705+
.rjsf .checkboxes-group {
706+
width: 100%;
707+
}
708+
709+
.rjsf .checkboxes-option {
710+
display: flex;
711+
align-items: center;
712+
gap: 0.5rem;
713+
padding: 4px 0;
714+
cursor: pointer;
715+
}
716+
717+
.rjsf .checkboxes-option.disabled {
718+
opacity: 0.5;
719+
cursor: not-allowed;
720+
}
721+
705722
.tooltip {
706723
z-index: 9999; /* A higher value than the modal */
707724
}

src/formBuilder/CardGeneralParameterInputs.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ export default function CardGeneralParameterInputs({
5959
"date",
6060
"time",
6161
"checkbox",
62+
"checkboxes",
6263
"radio",
6364
"dropdown",
6465
"shortAnswer",

src/formBuilder/defaults/defaultInputs.tsx

Lines changed: 68 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,53 @@ function MultipleChoice({
145145
)
146146
}
147147

148+
function MultipleChoiceArray({
149+
parameters,
150+
onChange,
151+
}: {
152+
parameters: CardComponentPropsType
153+
onChange: (newParams: CardComponentPropsType) => void
154+
}) {
155+
const items = (parameters.items as any) || {}
156+
const enumArray = Array.isArray(items.enum) ? items.enum : []
157+
const [elementId] = React.useState(getRandomId())
158+
159+
return (
160+
<div className="card-enum">
161+
<h5>Options</h5>
162+
<FBCheckbox
163+
onChangeValue={() => {
164+
const hasNames = Array.isArray(items.enumNames)
165+
onChange({
166+
...parameters,
167+
items: {
168+
...items,
169+
enumNames: hasNames ? null : enumArray.map((val: any) => `${val}`),
170+
},
171+
})
172+
}}
173+
isChecked={Array.isArray(items.enumNames)}
174+
label="Display different text label than the stored value"
175+
id={`${elementId}_different`}
176+
/>
177+
<CardEnumOptions
178+
initialValues={enumArray}
179+
names={
180+
Array.isArray(items.enumNames) ? items.enumNames.map((val: any) => `${val}`) : undefined
181+
}
182+
showNames={Array.isArray(items.enumNames)}
183+
onChange={(newEnum, newEnumNames) =>
184+
onChange({
185+
...parameters,
186+
items: { ...items, enum: newEnum, enumNames: newEnumNames },
187+
})
188+
}
189+
type="string"
190+
/>
191+
</div>
192+
)
193+
}
194+
148195
const defaultInputs: { [key: string]: FormInput } = {
149196
dateTime: {
150197
displayName: "Date-Time",
@@ -195,7 +242,7 @@ const defaultInputs: { [key: string]: FormInput } = {
195242
modalBody: CardDefaultParameterInputs,
196243
},
197244
checkbox: {
198-
displayName: "Checkbox",
245+
displayName: "Yes / No",
199246
matchIf: [
200247
{
201248
types: ["boolean"],
@@ -207,8 +254,27 @@ const defaultInputs: { [key: string]: FormInput } = {
207254
cardBody: Checkbox,
208255
modalBody: CardDefaultParameterInputs,
209256
},
257+
checkboxes: {
258+
displayName: "Checkboxes (Multi-select)",
259+
matchIf: [
260+
{
261+
types: ["array"],
262+
widget: "checkboxes",
263+
},
264+
],
265+
defaultDataSchema: {
266+
items: { type: "string", enum: [] },
267+
uniqueItems: true,
268+
},
269+
defaultUiSchema: {
270+
"ui:widget": "checkboxes",
271+
},
272+
type: "array",
273+
cardBody: MultipleChoiceArray,
274+
modalBody: CardDefaultParameterInputs,
275+
},
210276
radio: {
211-
displayName: "Radio",
277+
displayName: "Radio (Single-select)",
212278
matchIf: [
213279
{
214280
types: ["string", "number", "integer", "array", "boolean", "null"],

0 commit comments

Comments
 (0)