Skip to content

Commit 4ed6283

Browse files
committed
Add single select
1 parent cdaa0ac commit 4ed6283

File tree

1 file changed

+73
-10
lines changed
  • packages/carbon-component-mapper/src/files

1 file changed

+73
-10
lines changed

packages/carbon-component-mapper/src/files/select.js

Lines changed: 73 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,82 @@
1-
import React from 'react';
1+
import React, { useState, useEffect } from 'react';
22
import PropTypes from 'prop-types';
33
import { useFieldApi } from '@data-driven-forms/react-form-renderer';
44

5+
import DataDrivenSelect from '@data-driven-forms/common/src/select';
6+
import useIsMounted from '@data-driven-forms/common/src/hooks/use-is-mounted';
7+
import fnToString from '@data-driven-forms/common/src/utils/fn-to-string';
8+
9+
import { Select as CarbonSelect, MultiSelect, SelectItem } from 'carbon-components-react';
10+
import prepareProps from '../common/prepare-props';
11+
12+
const ClearedMultiSelectFilterable = (props) => {
13+
return 'multi.searchable';
14+
};
15+
16+
const ClearedMultiSelect = (props) => {
17+
return 'multi';
18+
};
19+
20+
const ClearedSelect = ({ invalidText, hideSelectedOptions, noOptionsMessage, onInputChange, options, isFetching, invalid, ...rest }) => {
21+
return (
22+
<CarbonSelect {...rest} if={rest.name} invalid={Boolean(invalidText)} invalidText={invalidText}>
23+
{options.map((option, index) => (
24+
<SelectItem key={option.value || index} text={option.label} {...option} />
25+
))}
26+
</CarbonSelect>
27+
);
28+
};
29+
530
const Select = (props) => {
6-
const { input, isDisabled, options } = useFieldApi(props);
31+
const { isMulti, isSearchable, loadOptions, input, meta, ...rest } = useFieldApi(prepareProps(props));
32+
33+
const [isFetching, setFetching] = useState(loadOptions ? true : false);
34+
const [options, setOptions] = useState(props.options || []);
35+
const isMounted = useIsMounted();
36+
37+
// common select controls the string of loadOptions and if the string changed, then it reloads options
38+
// however we are enhancing the loadOptions here so the string is always the same
39+
// by increasing this counter, we can enforce the update
40+
const [loadOptionsChangeCounter, setCounter] = useState(0);
41+
42+
const loadOptionsStr = fnToString(loadOptions);
43+
44+
useEffect(() => {
45+
setCounter(loadOptionsChangeCounter + 1);
46+
// eslint-disable-next-line react-hooks/exhaustive-deps
47+
}, [loadOptionsStr]);
48+
49+
const loadOptionsEnhanced = loadOptions
50+
? (value) => {
51+
if (isMounted.current) {
52+
setFetching(true);
53+
}
54+
55+
return loadOptions(value).then((data) => {
56+
if (isMounted.current) {
57+
setOptions([...options, ...data.filter(({ value }) => !options.find((option) => option.value === value))]);
58+
setFetching(false);
59+
}
60+
61+
return data;
62+
});
63+
}
64+
: undefined;
65+
66+
const Component = isMulti && isSearchable ? ClearedMultiSelectFilterable : isMulti ? ClearedMultiSelect : ClearedSelect;
67+
68+
const invalidText = (meta.touched && meta.error) || '';
769

870
return (
9-
<select {...input} disabled={isDisabled}>
10-
{options &&
11-
options.map((option) => (
12-
<option key={option.value} value={option.value}>
13-
{option.label}
14-
</option>
15-
))}
16-
</select>
71+
<DataDrivenSelect
72+
SelectComponent={Component}
73+
{...rest}
74+
{...input}
75+
invalidText={invalidText}
76+
loadOptionsChangeCounter={loadOptionsChangeCounter}
77+
loadOptions={loadOptionsEnhanced}
78+
simpleValue={false}
79+
/>
1780
);
1881
};
1982

0 commit comments

Comments
 (0)