forked from rjsf-team/react-jsonschema-form
/
SelectWidget.tsx
107 lines (100 loc) · 2.71 KB
/
SelectWidget.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
import React, { ChangeEvent, FocusEvent, useCallback } from "react";
import {
processSelectValue,
FormContextType,
RJSFSchema,
StrictRJSFSchema,
WidgetProps,
} from "@rjsf/utils";
function getValue(
event: React.SyntheticEvent<HTMLSelectElement>,
multiple: boolean
) {
if (multiple) {
return Array.from((event.target as HTMLSelectElement).options)
.slice()
.filter((o) => o.selected)
.map((o) => o.value);
}
return (event.target as HTMLSelectElement).value;
}
/** The `SelectWidget` is a widget for rendering dropdowns.
* It is typically used with string properties constrained with enum options.
*
* @param props - The `WidgetProps` for this component
*/
function SelectWidget<
T = any,
S extends StrictRJSFSchema = RJSFSchema,
F extends FormContextType = any
>({
schema,
id,
options,
value,
required,
disabled,
readonly,
multiple = false,
autofocus = false,
onChange,
onBlur,
onFocus,
placeholder,
}: WidgetProps<T, S, F>) {
const { enumOptions, enumDisabled } = options;
const emptyValue = multiple ? [] : "";
const handleFocus = useCallback(
(event: FocusEvent<HTMLSelectElement>) => {
const newValue = getValue(event, multiple);
return onFocus(
id,
processSelectValue<T, S, F>(schema, newValue, options)
);
},
[onFocus, id, schema, multiple, options]
);
const handleBlur = useCallback(
(event: FocusEvent<HTMLSelectElement>) => {
const newValue = getValue(event, multiple);
return onBlur(id, processSelectValue<T, S, F>(schema, newValue, options));
},
[onBlur, id, schema, multiple, options]
);
const handleChange = useCallback(
(event: ChangeEvent<HTMLSelectElement>) => {
const newValue = getValue(event, multiple);
return onChange(processSelectValue<T, S, F>(schema, newValue, options));
},
[onChange, schema, multiple, options]
);
return (
<select
id={id}
name={id}
multiple={multiple}
className="form-control"
value={typeof value === "undefined" ? emptyValue : value}
required={required}
disabled={disabled || readonly}
autoFocus={autofocus}
onBlur={handleBlur}
onFocus={handleFocus}
onChange={handleChange}
>
{!multiple && schema.default === undefined && (
<option value="">{placeholder}</option>
)}
{Array.isArray(enumOptions) &&
enumOptions.map(({ value, label }, i) => {
const disabled = enumDisabled && enumDisabled.indexOf(value) != -1;
return (
<option key={i} value={value} disabled={disabled}>
{label}
</option>
);
})}
</select>
);
}
export default SelectWidget;