summaryrefslogtreecommitdiffstats
path: root/src/components/ui/Select.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'src/components/ui/Select.tsx')
-rw-r--r--src/components/ui/Select.tsx112
1 files changed, 112 insertions, 0 deletions
diff --git a/src/components/ui/Select.tsx b/src/components/ui/Select.tsx
new file mode 100644
index 000000000..1d69a9acf
--- /dev/null
+++ b/src/components/ui/Select.tsx
@@ -0,0 +1,112 @@
1import {
2 createRef,
3 Component,
4 ReactElement,
5 RefObject,
6 ChangeEvent,
7} from 'react';
8import { observer } from 'mobx-react';
9import classnames from 'classnames';
10import { Field } from '../../@types/mobx-form.types';
11
12interface IProps {
13 field: Field;
14 className?: string;
15 showLabel?: boolean;
16 disabled?: boolean;
17 multiple?: boolean;
18}
19
20// Can this file be merged into the './select/index.tsx' file?
21@observer
22class Select extends Component<IProps> {
23 private element: RefObject<HTMLSelectElement> =
24 createRef<HTMLSelectElement>();
25
26 constructor(props: IProps) {
27 super(props);
28 }
29
30 multipleChange(e: ChangeEvent<HTMLSelectElement>): void {
31 e.preventDefault();
32 if (!this.element.current) {
33 return;
34 }
35 const result: string[] = [];
36 const { options } = this.element.current;
37 for (const option of options) {
38 if (option.selected && (option.value || option.text)) {
39 result.push(option.value || option.text);
40 }
41 }
42
43 const { field } = this.props;
44 field.value = result;
45 }
46
47 render(): ReactElement {
48 const {
49 field,
50 className = null,
51 showLabel = true,
52 disabled = false,
53 multiple = false,
54 } = this.props;
55
56 let selected = field.value;
57
58 if (multiple) {
59 if (typeof field.value === 'string' && field.value.slice(0, 1) === '[') {
60 // Value is JSON encoded
61 selected = JSON.parse(field.value);
62 } else if (typeof field.value === 'object') {
63 selected = field.value;
64 } else {
65 selected = [field.value];
66 }
67 }
68
69 return (
70 <div
71 className={classnames({
72 'franz-form__field': true,
73 'has-error': field.error,
74 'is-disabled': disabled,
75 [`${className}`]: className,
76 })}
77 >
78 {field.label && showLabel && (
79 <label className="franz-form__label" htmlFor={field.name}>
80 {field.label}
81 </label>
82 )}
83 <select
84 onChange={
85 multiple
86 ? (e: ChangeEvent<HTMLSelectElement>) => this.multipleChange(e)
87 : field.onChange
88 }
89 id={field.id}
90 defaultValue={selected}
91 className="franz-form__select"
92 disabled={field.disabled || disabled}
93 multiple={multiple}
94 ref={this.element}
95 >
96 {field.options!.map(type => (
97 <option
98 key={type.value}
99 value={type.value}
100 disabled={type.disabled}
101 >
102 {type.label}
103 </option>
104 ))}
105 </select>
106 {field.error && <div className="franz-form__error">{field.error}</div>}
107 </div>
108 );
109 }
110}
111
112export default Select;