diff --git a/src/lib/forms/SelectField.js b/src/lib/forms/SelectField.js index 5485a3cc..5071ddcb 100644 --- a/src/lib/forms/SelectField.js +++ b/src/lib/forms/SelectField.js @@ -12,6 +12,13 @@ import { Form } from "semantic-ui-react"; import { FeedbackLabel } from "../forms/FeedbackLabel"; export class SelectField extends Component { + constructor(props) { + super(props); + this.state = { + options: props.options || [], + }; + } + renderError = (meta, initialValue, initialErrors, value, errors) => { const { error, fieldPath } = this.props; const computedError = @@ -31,6 +38,23 @@ export class SelectField extends Component { ); }; + componentDidUpdate(prevProps) { + if (prevProps.options !== this.props.options) { + const nextOptions = this.props.options || []; + this.setState((prevState) => { + // Merge previous state options and new props options, de-duplicating by value + const existing = prevState.options || []; + const merged = [...existing]; + nextOptions.forEach((opt) => { + if (!merged.some((o) => o.value === opt.value)) { + merged.push(opt); + } + }); + return { options: merged }; + }); + } + } + renderFormField = (formikProps) => { const { form: { @@ -55,11 +79,42 @@ export class SelectField extends Component { multiple, disabled, required, + allowAdditions, ...uiProps } = cmpProps; const _defaultValue = multiple ? [] : ""; - const value = getIn(values, fieldPath, defaultValue || _defaultValue); + console.log("defaultValue:", defaultValue); + let value = getIn(values, fieldPath, defaultValue || _defaultValue); + // Fix: for multiple selects, normalize empty string to empty array + if (multiple && (value === "" || value === null || value === undefined)) { + value = []; + } const initialValue = getIn(initialValues, fieldPath, _defaultValue); + let dropdownOptions = + (this.state.options && this.state.options.length > 0 + ? this.state.options + : options) || []; + + // Ensure that all currently selected values are present in the options list + const ensureOptionPresent = (val) => { + if (val === undefined || val === null || val === "") return; + if (!dropdownOptions.some((opt) => opt.value === val)) { + dropdownOptions = [...dropdownOptions, { key: val, text: val, value: val }]; + } + }; + + if (multiple) { + if (Array.isArray(value)) { + value.forEach((v) => ensureOptionPresent(v)); + } else { + ensureOptionPresent(value); + } + } else { + ensureOptionPresent(value); + } + console.log("SelectField fieldPath:", fieldPath); + console.log("SelectField value:", value); + console.log("SelectField options:", dropdownOptions); return ( { if (onAddItem) { onAddItem({ event, data, formikProps }); + } else { + const newValue = data.value; + // Add the new option to the local options state (if not already present) + this.setState((prevState) => { + const prevOptions = prevState.options || []; + if (prevOptions.some((opt) => opt.value === newValue)) { + return null; + } + const newOption = { key: newValue, text: newValue, value: newValue }; + return { options: [...prevOptions, newOption] }; + }); + + // Update the Formik field value + if (multiple) { + const current = Array.isArray(value) + ? value + : value === undefined || value === null || value === "" + ? [] + : [value]; + setFieldValue(fieldPath, [...current, newValue]); + } else { + setFieldValue(fieldPath, newValue); + } } }} - options={options} + options={dropdownOptions} value={value} multiple={multiple} selectOnBlur={false} + allowAdditions={allowAdditions} {...uiProps} /> ); @@ -120,6 +199,7 @@ SelectField.propTypes = { label: PropTypes.oneOfType([PropTypes.string, PropTypes.node]), onChange: PropTypes.func, onAddItem: PropTypes.func, + allowAdditions: PropTypes.bool, multiple: PropTypes.bool, helpText: PropTypes.string, required: PropTypes.bool, @@ -137,4 +217,5 @@ SelectField.defaultProps = { helpText: undefined, required: false, disabled: false, + allowAdditions: false, }; diff --git a/src/lib/forms/widgets/select/Dropdown.js b/src/lib/forms/widgets/select/Dropdown.js index 1c1a5e20..3efdb6d0 100644 --- a/src/lib/forms/widgets/select/Dropdown.js +++ b/src/lib/forms/widgets/select/Dropdown.js @@ -31,6 +31,7 @@ class DropdownComponent extends Component { required, disabled, optimized, + allowAdditions, } = this.props; const helpText = helpTextProp ?? description; @@ -54,6 +55,7 @@ class DropdownComponent extends Component { defaultValue={multiple ? [] : ""} helpText={helpText} optimized={optimized} + allowAdditions={allowAdditions} /> ); } @@ -78,6 +80,7 @@ DropdownComponent.propTypes = { */ icon: PropTypes.string, optimized: PropTypes.bool, + allowAdditions: PropTypes.bool, ...fieldCommonProps, }; @@ -88,6 +91,7 @@ DropdownComponent.defaultProps = { clearable: true, description: undefined, optimized: true, + allowAdditions: false, }; export const Dropdown = showHideOverridableWithDynamicId(DropdownComponent);